Skip to content

Commit 5ec7457

Browse files
tsegismonttmonney
andauthored
Fix request absolute URI handling (#2833) (#2842)
* Fix request absolute URI handling When a request uses an absolute request target with scheme and host parts, the current absoluteURI() method simply concatenates the Host header value and the request target URI. For example, with the following request: ``` GET http://www.example.com:1234/path HTTP/1.1 Host: www.example.com:1234 ``` The result of HttpServerRequest.absoluteURI() would then be: `http://www.example.com:1234www.example.com:1234/path` With this change, when the request target is absolute, only the path (and query) are added to the Host value: `http://www.example.com:1234/path` Fixes #2830 * Update vertx-web/src/main/java/io/vertx/ext/web/impl/ForwardedParser.java --------- Co-authored-by: Thierry Monney <thierry.monney@gmail.com>
1 parent 54649c7 commit 5ec7457

File tree

2 files changed

+92
-2
lines changed

2 files changed

+92
-2
lines changed

vertx-web/src/main/java/io/vertx/ext/web/impl/ForwardedParser.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,16 @@ private void calculate() {
140140
if (host != null) {
141141
this.authority = HostAndPort.create(host, port);
142142
host = host + (port >= 0 ? ":" + port : "");
143-
absoluteURI = scheme + "://" + host + delegate.uri();
143+
144+
String uri = delegate.uri();
145+
if (uri.startsWith(scheme) && uri.startsWith("://", scheme.length())) {
146+
// URI is already absolute, only append the path and query
147+
uri = delegate.path();
148+
if (delegate.query() != null) {
149+
uri += "?" + delegate.query();
150+
}
151+
}
152+
absoluteURI = scheme + "://" + host + uri;
144153
}
145154
}
146155

@@ -195,7 +204,7 @@ private void calculateXForward() {
195204
}
196205
}
197206

198-
private void setHostAndPort(HostAndPort authority) {
207+
private void setHostAndPort(HostAndPort authority) {
199208
host = authority.host();
200209
port = authority.port();
201210
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* Copyright 2023 Red Hat, Inc.
3+
*
4+
* All rights reserved. This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License v1.0
6+
* and Apache License v2.0 which accompanies this distribution.
7+
*
8+
* The Eclipse Public License is available at
9+
* http://www.eclipse.org/legal/epl-v10.html
10+
*
11+
* The Apache License v2.0 is available at
12+
* http://www.opensource.org/licenses/apache2.0.php
13+
*
14+
* You may elect to redistribute this code under either of these licenses.
15+
*/
16+
package io.vertx.ext.web.impl;
17+
18+
import io.netty.handler.codec.http.HttpResponseStatus;
19+
import io.vertx.core.http.HttpMethod;
20+
import io.vertx.core.net.HostAndPort;
21+
import io.vertx.ext.web.WebTestBase;
22+
import org.junit.Test;
23+
import org.junit.runner.RunWith;
24+
import org.junit.runners.Parameterized;
25+
26+
import java.util.Arrays;
27+
28+
@RunWith(Parameterized.class)
29+
public class AbsoluteUriTest extends WebTestBase {
30+
31+
@Parameterized.Parameters(name = "target={0}, host={1}, query={2}")
32+
public static Iterable<Object[]> data() {
33+
return Arrays.asList(
34+
// absolute URI, no explicit authority, no query -> the authority in the URI is ignored
35+
new Object[]{"http://www.example.com:1234/some/path", null, null, "http://localhost:8080/some/path"},
36+
// absolute URI, no explicit authority, query present -> the authority in the URI is ignored
37+
new Object[]{"http://www.example.com:1234/some/path", null, "a=1&b=2", "http://localhost:8080/some/path?a=1&b=2"},
38+
// absolute URI, same explicit authority, no query
39+
new Object[]{"http://www.example.com:1234/some/path", "www.example.com:1234", null, "http://www.example.com:1234/some/path"},
40+
// absolute URI, same explicit authority, query present
41+
new Object[]{"http://www.example.com:1234/some/path", "www.example.com:1234", "a=1&b=2", "http://www.example.com:1234/some/path?a=1&b=2"},
42+
// absolute URI, different explicit authority, no query
43+
new Object[]{"http://www.example.com:1234/some/path", "another-host.com:5678", null, "http://another-host.com:5678/some/path"},
44+
// absolute URI, different explicit authority, query present
45+
new Object[]{"http://www.example.com:1234/some/path", "another-host.com:5678", "a=1&b=2", "http://another-host.com:5678/some/path?a=1&b=2"},
46+
// relative URI, no query
47+
new Object[]{"/some/path", "www.example.com:1234", null, "http://www.example.com:1234/some/path"},
48+
// relative URI, query present
49+
new Object[]{"/some/path", "www.example.com:1234", "a=1&b=2", "http://www.example.com:1234/some/path?a=1&b=2"}
50+
);
51+
}
52+
53+
private final String target;
54+
private final String authority;
55+
private final String query;
56+
private final String expectedAbsoluteUri;
57+
58+
public AbsoluteUriTest(String target, String authority, String query, String expectedAbsoluteUri) {
59+
this.target = target;
60+
this.authority = authority;
61+
this.query = query;
62+
this.expectedAbsoluteUri = expectedAbsoluteUri;
63+
}
64+
65+
@Test
66+
public void testAbsoluteUri() throws Exception {
67+
String uri = target + (query != null ? "?" + query : "");
68+
69+
router.route().handler(event -> {
70+
assertEquals(expectedAbsoluteUri, event.request().absoluteURI());
71+
assertEquals(uri, event.request().uri());
72+
event.response().end();
73+
});
74+
75+
testRequest(HttpMethod.GET, uri, request -> {
76+
if (authority != null) {
77+
request.authority(HostAndPort.parseAuthority(authority, 80));
78+
}
79+
}, HttpResponseStatus.OK.code(), HttpResponseStatus.OK.reasonPhrase(), null);
80+
}
81+
}

0 commit comments

Comments
 (0)