Skip to content

Commit

Permalink
Fix #6860 IPv6 Format (#6861)
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 21, 2021
1 parent a4cd421 commit 9b3fb19
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 18 deletions.
Expand Up @@ -57,6 +57,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.log.Log;
Expand Down Expand Up @@ -132,6 +133,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);
}

protected HttpInput newHttpInput(HttpChannelState state)
{
return new HttpInput(state);
Expand Down
34 changes: 19 additions & 15 deletions jetty-server/src/main/java/org/eclipse/jetty/server/Request.java
Expand Up @@ -998,7 +998,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 @@ -1014,7 +1014,7 @@ public String getLocalAddr()
String result = address == null
? local.getHostString()
: address.getHostAddress();
return HostPort.normalizeHost(result);
return formatAddrOrHost(result);
}

/*
Expand All @@ -1027,15 +1027,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 @@ -1257,12 +1257,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);
}

/*
Expand All @@ -1276,8 +1274,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());
}

/*
Expand Down Expand Up @@ -1403,7 +1402,7 @@ public String getScheme()
public String getServerName()
{
MetaData.Request metadata = _metaData;
String name = metadata == null ? null : metadata.getURI().getHost();
String name = metadata == null ? null : formatAddrOrHost(metadata.getURI().getHost());

// Return already determined host
if (name != null)
Expand All @@ -1425,19 +1424,19 @@ private String findServerName()
{
HostPortHttpField authority = (HostPortHttpField)host;
metadata.getURI().setAuthority(authority.getHost(), authority.getPort());
return authority.getHost();
return formatAddrOrHost(authority.getHost());
}
}

// 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 @@ -2604,4 +2603,9 @@ public <T extends HttpUpgradeHandler> T upgrade(Class<T> handlerClass) throws IO
{
throw new ServletException("HttpServletRequest.upgrade() not supported in Jetty");
}

private String formatAddrOrHost(String name)
{
return _channel == null ? HostPort.normalizeHost(name) : _channel.formatAddrOrHost(name);
}
}
Expand Up @@ -188,7 +188,7 @@ public enum ContextStatus
INITIALIZED,
DESTROYED
}

protected ContextStatus _contextStatus = ContextStatus.NOTSET;
protected Context _scontext;
private final AttributesMap _attributes;
Expand Down
Expand Up @@ -26,6 +26,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 All @@ -52,6 +55,8 @@
import org.eclipse.jetty.http.HttpComplianceSection;
import org.eclipse.jetty.http.HttpTester;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.LocalConnector.LocalEndPoint;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.ContextHandler;
Expand Down Expand Up @@ -96,12 +101,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, getHttpCompliance(), 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 @@ -933,6 +963,65 @@ public boolean check(HttpServletRequest request, HttpServletResponse response)
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 @@ -149,7 +149,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 9b3fb19

Please sign in to comment.