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>
This commit is contained in:
parent
f12c5b668c
commit
9a14de058d
|
@ -50,6 +50,7 @@ import org.eclipse.jetty.server.handler.ContextHandler;
|
||||||
import org.eclipse.jetty.server.handler.ErrorHandler;
|
import org.eclipse.jetty.server.handler.ErrorHandler;
|
||||||
import org.eclipse.jetty.util.BufferUtil;
|
import org.eclipse.jetty.util.BufferUtil;
|
||||||
import org.eclipse.jetty.util.Callback;
|
import org.eclipse.jetty.util.Callback;
|
||||||
|
import org.eclipse.jetty.util.HostPort;
|
||||||
import org.eclipse.jetty.util.SharedBlockingCallback.Blocker;
|
import org.eclipse.jetty.util.SharedBlockingCallback.Blocker;
|
||||||
import org.eclipse.jetty.util.StringUtil;
|
import org.eclipse.jetty.util.StringUtil;
|
||||||
import org.eclipse.jetty.util.thread.Scheduler;
|
import org.eclipse.jetty.util.thread.Scheduler;
|
||||||
|
@ -122,6 +123,15 @@ public abstract class HttpChannel implements Runnable, HttpOutput.Interceptor
|
||||||
return _state.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)
|
private HttpInput newHttpInput(HttpChannelState state)
|
||||||
{
|
{
|
||||||
return new HttpInput(state);
|
return new HttpInput(state);
|
||||||
|
|
|
@ -985,7 +985,7 @@ public class Request implements HttpServletRequest
|
||||||
String name = InetAddress.getLocalHost().getHostAddress();
|
String name = InetAddress.getLocalHost().getHostAddress();
|
||||||
if (StringUtil.ALL_INTERFACES.equals(name))
|
if (StringUtil.ALL_INTERFACES.equals(name))
|
||||||
return null;
|
return null;
|
||||||
return HostPort.normalizeHost(name);
|
return formatAddrOrHost(name);
|
||||||
}
|
}
|
||||||
catch (UnknownHostException e)
|
catch (UnknownHostException e)
|
||||||
{
|
{
|
||||||
|
@ -1001,7 +1001,7 @@ public class Request implements HttpServletRequest
|
||||||
String result = address == null
|
String result = address == null
|
||||||
? local.getHostString()
|
? local.getHostString()
|
||||||
: address.getHostAddress();
|
: address.getHostAddress();
|
||||||
return HostPort.normalizeHost(result);
|
return formatAddrOrHost(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1011,7 +1011,7 @@ public class Request implements HttpServletRequest
|
||||||
{
|
{
|
||||||
InetSocketAddress local = _channel.getLocalAddress();
|
InetSocketAddress local = _channel.getLocalAddress();
|
||||||
if (local != null)
|
if (local != null)
|
||||||
return HostPort.normalizeHost(local.getHostString());
|
return formatAddrOrHost(local.getHostString());
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -1019,7 +1019,7 @@ public class Request implements HttpServletRequest
|
||||||
String name = InetAddress.getLocalHost().getHostName();
|
String name = InetAddress.getLocalHost().getHostName();
|
||||||
if (StringUtil.ALL_INTERFACES.equals(name))
|
if (StringUtil.ALL_INTERFACES.equals(name))
|
||||||
return null;
|
return null;
|
||||||
return HostPort.normalizeHost(name);
|
return formatAddrOrHost(name);
|
||||||
}
|
}
|
||||||
catch (UnknownHostException e)
|
catch (UnknownHostException e)
|
||||||
{
|
{
|
||||||
|
@ -1211,12 +1211,10 @@ public class Request implements HttpServletRequest
|
||||||
|
|
||||||
InetAddress address = remote.getAddress();
|
InetAddress address = remote.getAddress();
|
||||||
String result = address == null
|
String result = address == null
|
||||||
? remote.getHostString()
|
? remote.getHostString()
|
||||||
: address.getHostAddress();
|
: address.getHostAddress();
|
||||||
// Add IPv6 brackets if necessary, to be consistent
|
|
||||||
// with cases where _remote has been built from other
|
return formatAddrOrHost(result);
|
||||||
// sources such as forward headers or PROXY protocol.
|
|
||||||
return HostPort.normalizeHost(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1227,8 +1225,9 @@ public class Request implements HttpServletRequest
|
||||||
remote = _channel.getRemoteAddress();
|
remote = _channel.getRemoteAddress();
|
||||||
if (remote == null)
|
if (remote == null)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
// We want the URI host, so add IPv6 brackets if necessary.
|
// We want the URI host, so add IPv6 brackets if necessary.
|
||||||
return HostPort.normalizeHost(remote.getHostString());
|
return formatAddrOrHost(remote.getHostString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1322,7 +1321,7 @@ public class Request implements HttpServletRequest
|
||||||
@Override
|
@Override
|
||||||
public String getServerName()
|
public String getServerName()
|
||||||
{
|
{
|
||||||
return _uri == null ? findServerName() : _uri.getHost();
|
return _uri == null ? findServerName() : formatAddrOrHost(_uri.getHost());
|
||||||
}
|
}
|
||||||
|
|
||||||
private String findServerName()
|
private String findServerName()
|
||||||
|
@ -1330,12 +1329,12 @@ public class Request implements HttpServletRequest
|
||||||
// Return host from connection
|
// Return host from connection
|
||||||
String name = getLocalName();
|
String name = getLocalName();
|
||||||
if (name != null)
|
if (name != null)
|
||||||
return HostPort.normalizeHost(name);
|
return formatAddrOrHost(name);
|
||||||
|
|
||||||
// Return the local host
|
// Return the local host
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return HostPort.normalizeHost(InetAddress.getLocalHost().getHostAddress());
|
return formatAddrOrHost(InetAddress.getLocalHost().getHostAddress());
|
||||||
}
|
}
|
||||||
catch (UnknownHostException e)
|
catch (UnknownHostException e)
|
||||||
{
|
{
|
||||||
|
@ -2541,4 +2540,9 @@ public class Request implements HttpServletRequest
|
||||||
// which we recover from the IncludeAttributes wrapper.
|
// which we recover from the IncludeAttributes wrapper.
|
||||||
return findServletPathMapping();
|
return findServletPathMapping();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String formatAddrOrHost(String name)
|
||||||
|
{
|
||||||
|
return _channel == null ? HostPort.normalizeHost(name) : _channel.formatAddrOrHost(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,9 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.Inet6Address;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
@ -59,6 +62,8 @@ import org.eclipse.jetty.http.MetaData;
|
||||||
import org.eclipse.jetty.http.MimeTypes;
|
import org.eclipse.jetty.http.MimeTypes;
|
||||||
import org.eclipse.jetty.http.UriCompliance;
|
import org.eclipse.jetty.http.UriCompliance;
|
||||||
import org.eclipse.jetty.http.pathmap.ServletPathSpec;
|
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.logging.StacklessLogging;
|
||||||
import org.eclipse.jetty.server.LocalConnector.LocalEndPoint;
|
import org.eclipse.jetty.server.LocalConnector.LocalEndPoint;
|
||||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||||
|
@ -105,12 +110,37 @@ public class RequestTest
|
||||||
private Server _server;
|
private Server _server;
|
||||||
private LocalConnector _connector;
|
private LocalConnector _connector;
|
||||||
private RequestHandler _handler;
|
private RequestHandler _handler;
|
||||||
|
private boolean _normalizeAddress = true;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void init() throws Exception
|
public void init() throws Exception
|
||||||
{
|
{
|
||||||
_server = new Server();
|
_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.setInputBufferSize(1024);
|
||||||
http.getHttpConfiguration().setRequestHeaderSize(512);
|
http.getHttpConfiguration().setRequestHeaderSize(512);
|
||||||
http.getHttpConfiguration().setResponseHeaderSize(512);
|
http.getHttpConfiguration().setResponseHeaderSize(512);
|
||||||
|
@ -858,6 +888,65 @@ public class RequestTest
|
||||||
assertEquals("8888", results.get(i));
|
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
|
@Test
|
||||||
public void testContent() throws Exception
|
public void testContent() throws Exception
|
||||||
{
|
{
|
||||||
|
|
|
@ -144,7 +144,7 @@ public class HostPort
|
||||||
public static String normalizeHost(String host)
|
public static String normalizeHost(String host)
|
||||||
{
|
{
|
||||||
// if it is normalized IPv6 or could not be IPv6, return
|
// 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;
|
return host;
|
||||||
|
|
||||||
// normalize with [ ]
|
// normalize with [ ]
|
||||||
|
|
Loading…
Reference in New Issue