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.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;
|
||||
|
@ -122,6 +123,15 @@ public abstract class HttpChannel implements Runnable, HttpOutput.Interceptor
|
|||
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);
|
||||
|
|
|
@ -985,7 +985,7 @@ public class Request implements HttpServletRequest
|
|||
String name = InetAddress.getLocalHost().getHostAddress();
|
||||
if (StringUtil.ALL_INTERFACES.equals(name))
|
||||
return null;
|
||||
return HostPort.normalizeHost(name);
|
||||
return formatAddrOrHost(name);
|
||||
}
|
||||
catch (UnknownHostException e)
|
||||
{
|
||||
|
@ -1001,7 +1001,7 @@ public class Request implements HttpServletRequest
|
|||
String result = address == null
|
||||
? local.getHostString()
|
||||
: address.getHostAddress();
|
||||
return HostPort.normalizeHost(result);
|
||||
return formatAddrOrHost(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1011,7 +1011,7 @@ public class Request implements HttpServletRequest
|
|||
{
|
||||
InetSocketAddress local = _channel.getLocalAddress();
|
||||
if (local != null)
|
||||
return HostPort.normalizeHost(local.getHostString());
|
||||
return formatAddrOrHost(local.getHostString());
|
||||
}
|
||||
|
||||
try
|
||||
|
@ -1019,7 +1019,7 @@ public class Request implements HttpServletRequest
|
|||
String name = InetAddress.getLocalHost().getHostName();
|
||||
if (StringUtil.ALL_INTERFACES.equals(name))
|
||||
return null;
|
||||
return HostPort.normalizeHost(name);
|
||||
return formatAddrOrHost(name);
|
||||
}
|
||||
catch (UnknownHostException e)
|
||||
{
|
||||
|
@ -1213,10 +1213,8 @@ public class Request implements HttpServletRequest
|
|||
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);
|
||||
|
||||
return formatAddrOrHost(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1227,8 +1225,9 @@ public class Request implements HttpServletRequest
|
|||
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
|
||||
|
@ -1322,7 +1321,7 @@ public class Request implements HttpServletRequest
|
|||
@Override
|
||||
public String getServerName()
|
||||
{
|
||||
return _uri == null ? findServerName() : _uri.getHost();
|
||||
return _uri == null ? findServerName() : formatAddrOrHost(_uri.getHost());
|
||||
}
|
||||
|
||||
private String findServerName()
|
||||
|
@ -1330,12 +1329,12 @@ public class Request implements HttpServletRequest
|
|||
// 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)
|
||||
{
|
||||
|
@ -2541,4 +2540,9 @@ public class Request implements HttpServletRequest
|
|||
// which we recover from the IncludeAttributes wrapper.
|
||||
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.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;
|
||||
|
@ -59,6 +62,8 @@ import org.eclipse.jetty.http.MetaData;
|
|||
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;
|
||||
|
@ -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);
|
||||
|
@ -858,6 +888,65 @@ public class RequestTest
|
|||
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
|
||||
{
|
||||
|
|
|
@ -144,7 +144,7 @@ public class HostPort
|
|||
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 [ ]
|
||||
|
|
Loading…
Reference in New Issue