Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #6860 IPv6 Format #6861

Merged
merged 8 commits into from Sep 21, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_channel is a final field. Can it ever be null?
If it is only null in tests, you may want to add a comment about that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should only be null in tests, but we have a specific test to check it works with null.

}
}
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