Skip to content

Commit

Permalink
Merge pull request #12940 from bobbyphilip/hostparsingerror
Browse files Browse the repository at this point in the history
Improved the parsing of the host and port in vertx
  • Loading branch information
gsmet authored Oct 27, 2020
2 parents b79b432 + a984bcd commit fb39c96
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,93 @@ public class ForwardedForHeaderTest {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addClasses(ForwardedHandlerInitializer.class)
.addAsResource(new StringAsset("quarkus.http.proxy.proxy-address-forwarding=true\n" +
"quarkus.http.proxy.enable-forwarded-host=true\n"),
"application.properties"));
.setArchiveProducer(
() -> ShrinkWrap.create(JavaArchive.class).addClasses(ForwardedHandlerInitializer.class)
.addAsResource(
new StringAsset("quarkus.http.proxy.proxy-address-forwarding=true\n"
+ "quarkus.http.proxy.enable-forwarded-host=true\n"),
"application.properties"));

@Test
public void test() {
assertThat(RestAssured.get("/forward").asString()).startsWith("http|");

RestAssured.given()
.header("X-Forwarded-Proto", "https")
.header("X-Forwarded-For", "backend:4444")
.header("X-Forwarded-Host", "somehost")
.get("/forward")
.then()
RestAssured.given().header("X-Forwarded-Proto", "https").header("X-Forwarded-For", "backend:4444")
.header("X-Forwarded-Host", "somehost").get("/forward").then()
.body(Matchers.equalTo("https|somehost|backend:4444"));
}

@Test
public void testIPV4WithPort() {
assertThat(RestAssured.get("/forward").asString()).startsWith("http|");

RestAssured.given().header("X-Forwarded-Proto", "https").header("X-Forwarded-For", "192.168.42.123:4444")
.header("X-Forwarded-Host", "somehost").get("/forward").then()
.body(Matchers.equalTo("https|somehost|192.168.42.123:4444"));
}

@Test
public void testIPV4NoPort() {
assertThat(RestAssured.get("/forward").asString()).startsWith("http|");

RestAssured.given().header("X-Forwarded-Proto", "https").header("X-Forwarded-For", "192.168.42.123")
.header("X-Forwarded-Host", "somehost").get("/forward").then()
.body(Matchers.containsString("192.168.42.123"));
}

@Test
public void testIPV6() {
assertThat(RestAssured.get("/forward").asString()).startsWith("http|");

RestAssured.given().header("X-Forwarded-Proto", "https")
.header("X-Forwarded-For", "2001:db8:85a3:8d3:1319:8a2e:370:12").header("X-Forwarded-Host", "somehost")
.get("/forward").then().body(Matchers.containsString("2001:db8:85a3:8d3:1319:8a2e:370:12"));
}

@Test
public void testIPV6HexEnding() {
assertThat(RestAssured.get("/forward").asString()).startsWith("http|");

RestAssured.given().header("X-Forwarded-Proto", "https")
.header("X-Forwarded-For", "2001:db8:85a3:8d3:1319:8a2e:370:ac").header("X-Forwarded-Host", "somehost")
.get("/forward").then().body(Matchers.containsString("2001:db8:85a3:8d3:1319:8a2e:370:ac"));
}

@Test
public void testIPV6Compressed() {
assertThat(RestAssured.get("/forward").asString()).startsWith("http|");

RestAssured.given().header("X-Forwarded-Proto", "https").header("X-Forwarded-For", "2001:db8:85a3::12")
.header("X-Forwarded-Host", "somehost").get("/forward").then()
.body(Matchers.containsString("2001:db8:85a3::12"));
}

@Test
public void testIPV6AnotherCompressed() {
assertThat(RestAssured.get("/forward").asString()).startsWith("http|");

RestAssured.given().header("X-Forwarded-Proto", "https").header("X-Forwarded-For", "2001:db8:85a3::")
.header("X-Forwarded-Host", "somehost").get("/forward").then()
.body(Matchers.containsString("2001:db8:85a3::"));
}

@Test
public void testIPV6WithPort() {
assertThat(RestAssured.get("/forward").asString()).startsWith("http|");

RestAssured.given().header("X-Forwarded-Proto", "https")
.header("X-Forwarded-For", "[2001:db8:85a3:8d3:1319:8a2e:370:ac]:101")
.header("X-Forwarded-Host", "somehost").get("/forward").then()
.body(Matchers.containsString("[2001:db8:85a3:8d3:1319:8a2e:370:ac]:101"));
}

@Test
public void testIPV6CompressedWithPort() {
assertThat(RestAssured.get("/forward").asString()).startsWith("http|");

RestAssured.given().header("X-Forwarded-Proto", "https").header("X-Forwarded-For", "[2001:db8:85a3:8d3::]:101")
.header("X-Forwarded-Host", "somehost").get("/forward").then()
.body(Matchers.containsString("[2001:db8:85a3:8d3::]:101"));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -178,29 +178,41 @@ private void calculate() {
}

private void setHostAndPort(String hostToParse, int defaultPort) {
int portSeparatorIdx = hostToParse.lastIndexOf(':');
if (portSeparatorIdx > hostToParse.lastIndexOf(']')) {
host = hostToParse.substring(0, portSeparatorIdx);
delegate.headers().set(HttpHeaders.HOST, host);
port = parsePort(hostToParse.substring(portSeparatorIdx + 1), defaultPort);
} else {
host = hostToParse;
port = -1;
}
String[] hostAndPort = parseHostAndPort(hostToParse);
host = hostAndPort[0];
delegate.headers().set(HttpHeaders.HOST, host);
port = parsePort(hostAndPort[1], defaultPort);
}

private SocketAddress parseFor(String forToParse, int defaultPort) {
String host = forToParse;
int port = defaultPort;
int portSeparatorIdx = forToParse.lastIndexOf(':');
if (portSeparatorIdx > forToParse.lastIndexOf(']')) {
host = forToParse.substring(0, portSeparatorIdx);
port = parsePort(forToParse.substring(portSeparatorIdx + 1), defaultPort);
}

String[] hostAndPort = parseHostAndPort(forToParse);
String host = hostAndPort[0];
int port = parsePort(hostAndPort[1], defaultPort);
return new SocketAddressImpl(port, host);
}

/**
* Returns a String[] of 2 elements, with the first being the host and the second the port
*/
private String[] parseHostAndPort(String hostToParse) {
String[] hostAndPort = { hostToParse, "" };
int portSeparatorIdx = hostToParse.lastIndexOf(':');
int squareBracketIdx = hostToParse.lastIndexOf(']');
if ((squareBracketIdx > -1 && portSeparatorIdx > squareBracketIdx)) {
// ipv6 with port
hostAndPort[0] = hostToParse.substring(0, portSeparatorIdx);
hostAndPort[1] = hostToParse.substring(portSeparatorIdx + 1);
} else {
long numberOfColons = hostToParse.chars().filter(ch -> ch == ':').count();
if (numberOfColons == 1 && !hostToParse.endsWith(":")) {
// ipv4 with port
hostAndPort[0] = hostToParse.substring(0, portSeparatorIdx);
hostAndPort[1] = hostToParse.substring(portSeparatorIdx + 1);
}
}
return hostAndPort;
}

private int parsePort(String portToParse, int defaultPort) {
if (portToParse != null && portToParse.length() > 0) {
try {
Expand Down

0 comments on commit fb39c96

Please sign in to comment.