Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions jooby/src/main/java/io/jooby/DefaultContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ default int getServerPort() {
@Override
default int getPort() {
var hostAndPort = getHostAndPort();
int index = hostAndPort.indexOf(':');
int index = portSeparator(hostAndPort);
if (index > 0) {
return Integer.parseInt(hostAndPort.substring(index + 1));
}
Expand All @@ -431,8 +431,26 @@ default int getPort() {
@Override
default String getHost() {
String hostAndPort = getHostAndPort();
int index = hostAndPort.indexOf(':');
return index > 0 ? hostAndPort.substring(0, index).trim() : hostAndPort;
int index = portSeparator(hostAndPort);
if (index > 0) {
return hostAndPort.substring(0, index).trim();
}
if (!hostAndPort.startsWith("[") && hostAndPort.indexOf(':') != hostAndPort.lastIndexOf(':')) {
// IPv6 address without port, which getHostAndPort() returns without brackets
return "[" + hostAndPort + "]";
}
return hostAndPort;
}

private static int portSeparator(String hostAndPort) {
int index = hostAndPort.lastIndexOf(':');
if (hostAndPort.startsWith("[")) {
// IPv6 address: the port follows the closing bracket, as in [::1]:8080
int end = hostAndPort.indexOf(']');
return end > 0 && index > end ? index : -1;
}
// more than one colon is an IPv6 address without brackets, so without port
return index == hostAndPort.indexOf(':') ? index : -1;
}

@Override
Expand Down
38 changes: 38 additions & 0 deletions jooby/src/test/java/io/jooby/DefaultContextTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,44 @@ void hostAndPortIPv6() {
doReturn(mockHostHeader).when(ctx).header("Host");

assertEquals("::1", ctx.getHostAndPort());
assertEquals("[::1]", ctx.getHost());
}

@Test
void hostAndPortIPv6WithPort() {
Value mockHostHeader = mock(Value.class);
when(mockHostHeader.valueOrNull()).thenReturn("[2001:db8::1]:8080");
doReturn(mockHostHeader).when(ctx).header("Host");

assertEquals("[2001:db8::1]:8080", ctx.getHostAndPort());
assertEquals("[2001:db8::1]", ctx.getHost());
assertEquals(8080, ctx.getPort());
}

@Test
void hostAndPortIPv6DefaultPort() {
doReturn(false).when(ctx).isSecure();

Value mockHostHeader = mock(Value.class);
when(mockHostHeader.valueOrNull()).thenReturn("[2001:db8::1]");
doReturn(mockHostHeader).when(ctx).header("Host");

assertEquals("[2001:db8::1]", ctx.getHost());
assertEquals(80, ctx.getPort());
}

@Test
void requestURLIPv6() {
doReturn("http").when(ctx).getScheme();
doReturn("/").when(ctx).getContextPath();
doReturn("/path").when(ctx).getRequestPath();
doReturn("?q=1").when(ctx).queryString();

Value mockHostHeader = mock(Value.class);
when(mockHostHeader.valueOrNull()).thenReturn("[::1]:8080");
doReturn(mockHostHeader).when(ctx).header("Host");

assertEquals("http://[::1]:8080/path?q=1", ctx.getRequestURL());
}

@Test
Expand Down
Loading