Skip to content

Commit

Permalink
Fix #6860 IPv6 Format (#6861) (#6885)
Browse files Browse the repository at this point in the history
Fix #6860 IPv6 format by adding an extensible HttpChannel method

Signed-off-by: Greg Wilkins <gregw@webtide.com>
Co-authored-by: Lachlan Roberts <lachlan@webtide.com>
  • Loading branch information
gregw and lachlan-roberts committed Sep 22, 2021
1 parent f12c5b6 commit 9a14de0
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 16 deletions.
Expand Up @@ -50,6 +50,7 @@
import org.eclipse.jetty.server.handler.ErrorHandler;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.HostPort;
import org.eclipse.jetty.util.SharedBlockingCallback.Blocker;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.thread.Scheduler;
Expand Down Expand Up @@ -122,6 +123,15 @@ public boolean isSendError()
return _state.isSendError();
}

/** Format the address or host returned from Request methods
* @param addr The address or host
* @return Default implementation returns {@link HostPort#normalizeHost(String)}
*/
protected String formatAddrOrHost(String addr)
{
return HostPort.normalizeHost(addr);
}

private HttpInput newHttpInput(HttpChannelState state)
{
return new HttpInput(state);
Expand Down
32 changes: 18 additions & 14 deletions jetty-server/src/main/java/org/eclipse/jetty/server/Request.java
Expand Up @@ -985,7 +985,7 @@ public String getLocalAddr()
String name = InetAddress.getLocalHost().getHostAddress();
if (StringUtil.ALL_INTERFACES.equals(name))
return null;
return HostPort.normalizeHost(name);
return formatAddrOrHost(name);
}
catch (UnknownHostException e)
{
Expand All @@ -1001,7 +1001,7 @@ public String getLocalAddr()
String result = address == null
? local.getHostString()
: address.getHostAddress();
return HostPort.normalizeHost(result);
return formatAddrOrHost(result);
}

@Override
Expand All @@ -1011,15 +1011,15 @@ public String getLocalName()
{
InetSocketAddress local = _channel.getLocalAddress();
if (local != null)
return HostPort.normalizeHost(local.getHostString());
return formatAddrOrHost(local.getHostString());
}

try
{
String name = InetAddress.getLocalHost().getHostName();
if (StringUtil.ALL_INTERFACES.equals(name))
return null;
return HostPort.normalizeHost(name);
return formatAddrOrHost(name);
}
catch (UnknownHostException e)
{
Expand Down Expand Up @@ -1211,12 +1211,10 @@ public String getRemoteAddr()

InetAddress address = remote.getAddress();
String result = address == null
? remote.getHostString()
: address.getHostAddress();
// Add IPv6 brackets if necessary, to be consistent
// with cases where _remote has been built from other
// sources such as forward headers or PROXY protocol.
return HostPort.normalizeHost(result);
? remote.getHostString()
: address.getHostAddress();

return formatAddrOrHost(result);
}

@Override
Expand All @@ -1227,8 +1225,9 @@ public String getRemoteHost()
remote = _channel.getRemoteAddress();
if (remote == null)
return "";

// We want the URI host, so add IPv6 brackets if necessary.
return HostPort.normalizeHost(remote.getHostString());
return formatAddrOrHost(remote.getHostString());
}

@Override
Expand Down Expand Up @@ -1322,20 +1321,20 @@ public String getScheme()
@Override
public String getServerName()
{
return _uri == null ? findServerName() : _uri.getHost();
return _uri == null ? findServerName() : formatAddrOrHost(_uri.getHost());
}

private String findServerName()
{
// Return host from connection
String name = getLocalName();
if (name != null)
return HostPort.normalizeHost(name);
return formatAddrOrHost(name);

// Return the local host
try
{
return HostPort.normalizeHost(InetAddress.getLocalHost().getHostAddress());
return formatAddrOrHost(InetAddress.getLocalHost().getHostAddress());
}
catch (UnknownHostException e)
{
Expand Down Expand Up @@ -2541,4 +2540,9 @@ public HttpServletMapping getHttpServletMapping()
// which we recover from the IncludeAttributes wrapper.
return findServletPathMapping();
}

private String formatAddrOrHost(String name)
{
return _channel == null ? HostPort.normalizeHost(name) : _channel.formatAddrOrHost(name);
}
}
Expand Up @@ -20,6 +20,9 @@
import java.io.InputStream;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
Expand Down Expand Up @@ -59,6 +62,8 @@
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.http.UriCompliance;
import org.eclipse.jetty.http.pathmap.ServletPathSpec;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.logging.StacklessLogging;
import org.eclipse.jetty.server.LocalConnector.LocalEndPoint;
import org.eclipse.jetty.server.handler.AbstractHandler;
Expand Down Expand Up @@ -105,12 +110,37 @@ public class RequestTest
private Server _server;
private LocalConnector _connector;
private RequestHandler _handler;
private boolean _normalizeAddress = true;

@BeforeEach
public void init() throws Exception
{
_server = new Server();
HttpConnectionFactory http = new HttpConnectionFactory();
HttpConnectionFactory http = new HttpConnectionFactory()
{
@Override
public Connection newConnection(Connector connector, EndPoint endPoint)
{
HttpConnection conn = new HttpConnection(getHttpConfiguration(), connector, endPoint, isRecordHttpComplianceViolations())
{
@Override
protected HttpChannelOverHttp newHttpChannel()
{
return new HttpChannelOverHttp(this, getConnector(), getHttpConfiguration(), getEndPoint(), this)
{
@Override
protected String formatAddrOrHost(String addr)
{
if (_normalizeAddress)
return super.formatAddrOrHost(addr);
return addr;
}
};
}
};
return configure(conn, connector, endPoint);
}
};
http.setInputBufferSize(1024);
http.getHttpConfiguration().setRequestHeaderSize(512);
http.getHttpConfiguration().setResponseHeaderSize(512);
Expand Down Expand Up @@ -858,6 +888,65 @@ public void testHostPort() throws Exception
assertEquals("8888", results.get(i));
}

@Test
public void testIPv6() throws Exception
{
final ArrayList<String> results = new ArrayList<>();
final InetAddress local = Inet6Address.getByAddress("localIPv6", new byte[]{
0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8
});
final InetSocketAddress localAddr = new InetSocketAddress(local, 32768);
_handler._checker = new RequestTester()
{
@Override
public boolean check(HttpServletRequest request, HttpServletResponse response)
{
((Request)request).setRemoteAddr(localAddr);
results.add(request.getRemoteAddr());
results.add(request.getRemoteHost());
results.add(Integer.toString(request.getRemotePort()));
results.add(request.getServerName());
results.add(Integer.toString(request.getServerPort()));
results.add(request.getLocalAddr());
results.add(Integer.toString(request.getLocalPort()));
return true;
}
};

_normalizeAddress = true;
String response = _connector.getResponse(
"GET / HTTP/1.1\n" +
"Host: [::1]:8888\n" +
"Connection: close\n" +
"\n");
int i = 0;
assertThat(response, containsString("200 OK"));
assertEquals("[1:2:3:4:5:6:7:8]", results.get(i++));
assertEquals("localIPv6", results.get(i++));
assertEquals("32768", results.get(i++));
assertEquals("[::1]", results.get(i++));
assertEquals("8888", results.get(i++));
assertEquals("0.0.0.0", results.get(i++));
assertEquals("0", results.get(i));

_normalizeAddress = false;
results.clear();
response = _connector.getResponse(
"GET / HTTP/1.1\n" +
"Host: [::1]:8888\n" +
"Connection: close\n" +
"\n");
i = 0;
assertThat(response, containsString("200 OK"));
assertEquals("1:2:3:4:5:6:7:8", results.get(i++));
assertEquals("localIPv6", results.get(i++));
assertEquals("32768", results.get(i++));
assertEquals("[::1]", results.get(i++));
assertEquals("8888", results.get(i++));
assertEquals("0.0.0.0", results.get(i++));
assertEquals("0", results.get(i));
}

@Test
public void testContent() throws Exception
{
Expand Down
Expand Up @@ -144,7 +144,7 @@ public String toString()
public static String normalizeHost(String host)
{
// if it is normalized IPv6 or could not be IPv6, return
if (host.isEmpty() || host.charAt(0) == '[' || host.indexOf(':') < 0)
if (host == null || host.isEmpty() || host.charAt(0) == '[' || host.indexOf(':') < 0)
return host;

// normalize with [ ]
Expand Down

0 comments on commit 9a14de0

Please sign in to comment.