mirror of
https://github.com/jetty/jetty.project.git
synced 2025-03-01 03:19:13 +00:00
Fixes #5079 - :authority header for IPv6 address not having square brackets.
On the client: * Origin.Address.host is passed through HostPort.normalizeHost(), so that if it is IPv6 is bracketed. Now the ipv6 address passed to an `HttClient` request is bracketed. * HttpRequest was de-bracketing the host, but now it does not anymore. On the server: * Request.getLocalAddr(), getLocalName(), getRemoteAddr(), getRemoteHost(), getServerName(), when dealing with an IPv6 address, return it bracketed. The reason to return bracketed IPv6 also from *Addr() methods is that if it is used with InetAddress/InetSocketAddress it still works, but often it is interpreted as a URI host so brackets are necessary. * DoSFilter was blindly bracketing - now it does not. Added a number of test cases, and fixed those that expected non-bracketed IPv6. Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
This commit is contained in:
parent
1f14dfa427
commit
d53d9d8a1d
@ -27,6 +27,7 @@ import org.eclipse.jetty.server.Server;
|
|||||||
import org.eclipse.jetty.util.component.LifeCycle;
|
import org.eclipse.jetty.util.component.LifeCycle;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Tag;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
@ -54,8 +55,10 @@ public class OneWebAppTest extends AbstractEmbeddedTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Tag("external")
|
||||||
public void testGetAsyncRest() throws Exception
|
public void testGetAsyncRest() throws Exception
|
||||||
{
|
{
|
||||||
|
// The async rest webapp forwards the call to ebay.com.
|
||||||
URI uri = server.getURI().resolve("/testAsync?items=mouse,beer,gnome");
|
URI uri = server.getURI().resolve("/testAsync?items=mouse,beer,gnome");
|
||||||
ContentResponse response = client.newRequest(uri)
|
ContentResponse response = client.newRequest(uri)
|
||||||
.method(HttpMethod.GET)
|
.method(HttpMethod.GET)
|
||||||
|
@ -1155,10 +1155,14 @@ public class HttpClient extends ContainerLifeCycle
|
|||||||
return encodingField;
|
return encodingField;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param host the host to normalize
|
||||||
|
* @return the host itself
|
||||||
|
* @deprecated no replacement, do not use it
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
protected String normalizeHost(String host)
|
protected String normalizeHost(String host)
|
||||||
{
|
{
|
||||||
if (host != null && host.startsWith("[") && host.endsWith("]"))
|
|
||||||
return host.substring(1, host.length() - 1);
|
|
||||||
return host;
|
return host;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ public class HttpRequest implements Request
|
|||||||
this.client = client;
|
this.client = client;
|
||||||
this.conversation = conversation;
|
this.conversation = conversation;
|
||||||
scheme = uri.getScheme();
|
scheme = uri.getScheme();
|
||||||
host = client.normalizeHost(uri.getHost());
|
host = uri.getHost();
|
||||||
port = HttpClient.normalizePort(scheme, uri.getPort());
|
port = HttpClient.normalizePort(scheme, uri.getPort());
|
||||||
path = uri.getRawPath();
|
path = uri.getRawPath();
|
||||||
query = uri.getRawQuery();
|
query = uri.getRawQuery();
|
||||||
|
@ -20,6 +20,7 @@ package org.eclipse.jetty.client;
|
|||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.util.HostPort;
|
||||||
import org.eclipse.jetty.util.URIUtil;
|
import org.eclipse.jetty.util.URIUtil;
|
||||||
|
|
||||||
public class Origin
|
public class Origin
|
||||||
@ -107,7 +108,7 @@ public class Origin
|
|||||||
|
|
||||||
public Address(String host, int port)
|
public Address(String host, int port)
|
||||||
{
|
{
|
||||||
this.host = Objects.requireNonNull(host);
|
this.host = HostPort.normalizeHost(Objects.requireNonNull(host));
|
||||||
this.port = port;
|
this.port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1623,29 +1623,32 @@ public class HttpClientTest extends AbstractHttpClientServerTest
|
|||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@ArgumentsSource(ScenarioProvider.class)
|
@ArgumentsSource(ScenarioProvider.class)
|
||||||
public void testIPv6Host(Scenario scenario) throws Exception
|
public void testIPv6HostWithHTTP10(Scenario scenario) throws Exception
|
||||||
{
|
{
|
||||||
Assumptions.assumeTrue(Net.isIpv6InterfaceAvailable());
|
Assumptions.assumeTrue(Net.isIpv6InterfaceAvailable());
|
||||||
start(scenario, new AbstractHandler()
|
start(scenario, new EmptyServerHandler()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException
|
protected void service(String target, org.eclipse.jetty.server.Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException
|
||||||
{
|
{
|
||||||
baseRequest.setHandled(true);
|
|
||||||
response.setContentType("text/plain");
|
response.setContentType("text/plain");
|
||||||
response.getOutputStream().print(request.getHeader("Host"));
|
response.getOutputStream().print(request.getServerName());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
URI uri = URI.create(scenario.getScheme() + "://[::1]:" + connector.getLocalPort() + "/path");
|
URI uri = URI.create(scenario.getScheme() + "://[::1]:" + connector.getLocalPort() + "/path");
|
||||||
ContentResponse response = client.newRequest(uri)
|
ContentResponse response = client.newRequest(uri)
|
||||||
.method(HttpMethod.PUT)
|
.method(HttpMethod.PUT)
|
||||||
|
.version(HttpVersion.HTTP_1_0)
|
||||||
|
.onRequestBegin(r -> r.getHeaders().remove(HttpHeader.HOST))
|
||||||
.timeout(5, TimeUnit.SECONDS)
|
.timeout(5, TimeUnit.SECONDS)
|
||||||
.send();
|
.send();
|
||||||
|
|
||||||
assertNotNull(response);
|
assertNotNull(response);
|
||||||
assertEquals(200, response.getStatus());
|
assertEquals(200, response.getStatus());
|
||||||
assertThat(new String(response.getContent(), StandardCharsets.ISO_8859_1), Matchers.startsWith("[::1]:"));
|
String content = response.getContentAsString();
|
||||||
|
assertThat(content, Matchers.startsWith("["));
|
||||||
|
assertThat(content, Matchers.endsWith(":1]"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
|
@ -67,8 +67,10 @@ public class HttpClientURITest extends AbstractHttpClientServerTest
|
|||||||
Assumptions.assumeTrue(Net.isIpv6InterfaceAvailable());
|
Assumptions.assumeTrue(Net.isIpv6InterfaceAvailable());
|
||||||
start(scenario, new EmptyServerHandler());
|
start(scenario, new EmptyServerHandler());
|
||||||
|
|
||||||
String host = "::1";
|
String hostAddress = "::1";
|
||||||
Request request = client.newRequest(host, connector.getLocalPort())
|
String host = "[" + hostAddress + "]";
|
||||||
|
// Explicitly use a non-bracketed IPv6 host.
|
||||||
|
Request request = client.newRequest(hostAddress, connector.getLocalPort())
|
||||||
.scheme(scenario.getScheme())
|
.scheme(scenario.getScheme())
|
||||||
.timeout(5, TimeUnit.SECONDS);
|
.timeout(5, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// All rights reserved. This program and the accompanying materials
|
||||||
|
// are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
// and Apache License v2.0 which accompanies this distribution.
|
||||||
|
//
|
||||||
|
// The Eclipse Public License is available at
|
||||||
|
// http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
//
|
||||||
|
// The Apache License v2.0 is available at
|
||||||
|
// http://www.opensource.org/licenses/apache2.0.php
|
||||||
|
//
|
||||||
|
// You may elect to redistribute this code under either of these licenses.
|
||||||
|
// ========================================================================
|
||||||
|
//
|
||||||
|
|
||||||
|
package org.eclipse.jetty.proxy;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.server.Request;
|
||||||
|
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||||
|
|
||||||
|
public class EmptyServerHandler extends AbstractHandler
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public final void handle(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||||
|
{
|
||||||
|
jettyRequest.setHandled(true);
|
||||||
|
service(target, jettyRequest, request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -21,10 +21,14 @@ package org.eclipse.jetty.proxy;
|
|||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.eclipse.jetty.client.HttpClient;
|
import org.eclipse.jetty.client.HttpClient;
|
||||||
import org.eclipse.jetty.client.HttpProxy;
|
import org.eclipse.jetty.client.HttpProxy;
|
||||||
import org.eclipse.jetty.client.api.ContentResponse;
|
import org.eclipse.jetty.client.api.ContentResponse;
|
||||||
|
import org.eclipse.jetty.client.api.Request;
|
||||||
|
import org.eclipse.jetty.http.HttpHeader;
|
||||||
import org.eclipse.jetty.http.HttpMethod;
|
import org.eclipse.jetty.http.HttpMethod;
|
||||||
import org.eclipse.jetty.http.HttpStatus;
|
import org.eclipse.jetty.http.HttpStatus;
|
||||||
import org.eclipse.jetty.io.AbstractConnection;
|
import org.eclipse.jetty.io.AbstractConnection;
|
||||||
@ -33,9 +37,14 @@ import org.eclipse.jetty.io.EndPoint;
|
|||||||
import org.eclipse.jetty.server.AbstractConnectionFactory;
|
import org.eclipse.jetty.server.AbstractConnectionFactory;
|
||||||
import org.eclipse.jetty.server.ConnectionFactory;
|
import org.eclipse.jetty.server.ConnectionFactory;
|
||||||
import org.eclipse.jetty.server.Connector;
|
import org.eclipse.jetty.server.Connector;
|
||||||
|
import org.eclipse.jetty.server.ForwardedRequestCustomizer;
|
||||||
|
import org.eclipse.jetty.server.Handler;
|
||||||
|
import org.eclipse.jetty.server.HttpConfiguration;
|
||||||
|
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||||
import org.eclipse.jetty.server.Server;
|
import org.eclipse.jetty.server.Server;
|
||||||
import org.eclipse.jetty.server.ServerConnector;
|
import org.eclipse.jetty.server.ServerConnector;
|
||||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||||
import org.eclipse.jetty.util.BufferUtil;
|
import org.eclipse.jetty.util.BufferUtil;
|
||||||
import org.eclipse.jetty.util.Callback;
|
import org.eclipse.jetty.util.Callback;
|
||||||
@ -44,10 +53,13 @@ import org.eclipse.jetty.util.ssl.SslContextFactory;
|
|||||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||||
import org.hamcrest.Matchers;
|
import org.hamcrest.Matchers;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
import org.junit.jupiter.params.provider.ValueSource;
|
||||||
|
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.greaterThan;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
|
||||||
@ -73,7 +85,7 @@ public class ForwardProxyServerTest
|
|||||||
private Server proxy;
|
private Server proxy;
|
||||||
private ServerConnector proxyConnector;
|
private ServerConnector proxyConnector;
|
||||||
|
|
||||||
protected void startServer(SslContextFactory.Server serverTLS, ConnectionFactory connectionFactory) throws Exception
|
protected void startServer(SslContextFactory.Server serverTLS, ConnectionFactory connectionFactory, Handler handler) throws Exception
|
||||||
{
|
{
|
||||||
serverSslContextFactory = serverTLS;
|
serverSslContextFactory = serverTLS;
|
||||||
QueuedThreadPool serverThreads = new QueuedThreadPool();
|
QueuedThreadPool serverThreads = new QueuedThreadPool();
|
||||||
@ -81,10 +93,11 @@ public class ForwardProxyServerTest
|
|||||||
server = new Server(serverThreads);
|
server = new Server(serverThreads);
|
||||||
serverConnector = new ServerConnector(server, serverSslContextFactory, connectionFactory);
|
serverConnector = new ServerConnector(server, serverSslContextFactory, connectionFactory);
|
||||||
server.addConnector(serverConnector);
|
server.addConnector(serverConnector);
|
||||||
|
server.setHandler(handler);
|
||||||
server.start();
|
server.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void startProxy() throws Exception
|
protected void startProxy(ProxyServlet proxyServlet) throws Exception
|
||||||
{
|
{
|
||||||
QueuedThreadPool proxyThreads = new QueuedThreadPool();
|
QueuedThreadPool proxyThreads = new QueuedThreadPool();
|
||||||
proxyThreads.setName("proxy");
|
proxyThreads.setName("proxy");
|
||||||
@ -98,7 +111,7 @@ public class ForwardProxyServerTest
|
|||||||
proxy.setHandler(connectHandler);
|
proxy.setHandler(connectHandler);
|
||||||
|
|
||||||
ServletContextHandler proxyHandler = new ServletContextHandler(connectHandler, "/");
|
ServletContextHandler proxyHandler = new ServletContextHandler(connectHandler, "/");
|
||||||
proxyHandler.addServlet(ProxyServlet.class, "/*");
|
proxyHandler.addServlet(new ServletHolder(proxyServlet), "/*");
|
||||||
|
|
||||||
proxy.start();
|
proxy.start();
|
||||||
}
|
}
|
||||||
@ -165,7 +178,7 @@ public class ForwardProxyServerTest
|
|||||||
// the client, and convert it to a relative URI.
|
// the client, and convert it to a relative URI.
|
||||||
// The ConnectHandler won't modify what the client
|
// The ConnectHandler won't modify what the client
|
||||||
// sent, which must be a relative URI.
|
// sent, which must be a relative URI.
|
||||||
assertThat(request.length(), Matchers.greaterThan(0));
|
assertThat(request.length(), greaterThan(0));
|
||||||
if (serverSslContextFactory == null)
|
if (serverSslContextFactory == null)
|
||||||
assertFalse(request.contains("http://"));
|
assertFalse(request.contains("http://"));
|
||||||
else
|
else
|
||||||
@ -185,8 +198,8 @@ public class ForwardProxyServerTest
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
}, new EmptyServerHandler());
|
||||||
startProxy();
|
startProxy(new ProxyServlet());
|
||||||
|
|
||||||
SslContextFactory.Client clientTLS = new SslContextFactory.Client(true);
|
SslContextFactory.Client clientTLS = new SslContextFactory.Client(true);
|
||||||
HttpClient httpClient = new HttpClient(clientTLS);
|
HttpClient httpClient = new HttpClient(clientTLS);
|
||||||
@ -208,4 +221,79 @@ public class ForwardProxyServerTest
|
|||||||
httpClient.stop();
|
httpClient.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(strings = {"::2", "[::3]"})
|
||||||
|
public void testIPv6WithXForwardedForHeader(String ipv6) throws Exception
|
||||||
|
{
|
||||||
|
HttpConfiguration httpConfig = new HttpConfiguration();
|
||||||
|
httpConfig.addCustomizer(new ForwardedRequestCustomizer());
|
||||||
|
ConnectionFactory http = new HttpConnectionFactory(httpConfig);
|
||||||
|
startServer(null, http, new EmptyServerHandler()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void service(String target, org.eclipse.jetty.server.Request jettyRequest, HttpServletRequest request, HttpServletResponse response)
|
||||||
|
{
|
||||||
|
String remoteHost = jettyRequest.getRemoteHost();
|
||||||
|
assertThat(remoteHost, Matchers.matchesPattern("\\[.+\\]"));
|
||||||
|
String remoteAddr = jettyRequest.getRemoteAddr();
|
||||||
|
assertThat(remoteAddr, Matchers.matchesPattern("\\[.+\\]"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
startProxy(new ProxyServlet()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void addProxyHeaders(HttpServletRequest clientRequest, Request proxyRequest)
|
||||||
|
{
|
||||||
|
proxyRequest.header(HttpHeader.X_FORWARDED_FOR, ipv6);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
HttpClient httpClient = new HttpClient();
|
||||||
|
httpClient.getProxyConfiguration().getProxies().add(newHttpProxy());
|
||||||
|
httpClient.start();
|
||||||
|
|
||||||
|
ContentResponse response = httpClient.newRequest("[::1]", serverConnector.getLocalPort())
|
||||||
|
.scheme("http")
|
||||||
|
.send();
|
||||||
|
|
||||||
|
assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIPv6WithForwardedHeader() throws Exception
|
||||||
|
{
|
||||||
|
HttpConfiguration httpConfig = new HttpConfiguration();
|
||||||
|
httpConfig.addCustomizer(new ForwardedRequestCustomizer());
|
||||||
|
ConnectionFactory http = new HttpConnectionFactory(httpConfig);
|
||||||
|
startServer(null, http, new EmptyServerHandler()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void service(String target, org.eclipse.jetty.server.Request jettyRequest, HttpServletRequest request, HttpServletResponse response)
|
||||||
|
{
|
||||||
|
String remoteHost = jettyRequest.getRemoteHost();
|
||||||
|
assertThat(remoteHost, Matchers.matchesPattern("\\[.+\\]"));
|
||||||
|
String remoteAddr = jettyRequest.getRemoteAddr();
|
||||||
|
assertThat(remoteAddr, Matchers.matchesPattern("\\[.+\\]"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
startProxy(new ProxyServlet()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void addProxyHeaders(HttpServletRequest clientRequest, Request proxyRequest)
|
||||||
|
{
|
||||||
|
proxyRequest.header(HttpHeader.FORWARDED, "for=\"[::2]\"");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
HttpClient httpClient = new HttpClient();
|
||||||
|
httpClient.getProxyConfiguration().getProxies().add(newHttpProxy());
|
||||||
|
httpClient.start();
|
||||||
|
|
||||||
|
ContentResponse response = httpClient.newRequest("[::1]", serverConnector.getLocalPort())
|
||||||
|
.scheme("http")
|
||||||
|
.send();
|
||||||
|
|
||||||
|
assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -463,6 +463,34 @@ public class ForwardProxyTLSServerTest
|
|||||||
httpClient.stop();
|
httpClient.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("proxyTLS")
|
||||||
|
public void testIPv6(SslContextFactory.Server proxyTLS) throws Exception
|
||||||
|
{
|
||||||
|
startTLSServer(new ServerHandler());
|
||||||
|
startProxy(proxyTLS);
|
||||||
|
|
||||||
|
HttpClient httpClient = new HttpClient(newClientSslContextFactory());
|
||||||
|
HttpProxy httpProxy = new HttpProxy(new Origin.Address("[::1]", proxyConnector.getLocalPort()), proxyTLS != null);
|
||||||
|
httpClient.getProxyConfiguration().getProxies().add(httpProxy);
|
||||||
|
httpClient.start();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ContentResponse response = httpClient.newRequest("[::1]", serverConnector.getLocalPort())
|
||||||
|
.scheme(HttpScheme.HTTPS.asString())
|
||||||
|
.path("/echo?body=")
|
||||||
|
.timeout(5, TimeUnit.SECONDS)
|
||||||
|
.send();
|
||||||
|
|
||||||
|
assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
httpClient.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("proxyTLS")
|
@MethodSource("proxyTLS")
|
||||||
public void testProxyAuthentication(SslContextFactory.Server proxyTLS) throws Exception
|
public void testProxyAuthentication(SslContextFactory.Server proxyTLS) throws Exception
|
||||||
|
@ -27,6 +27,7 @@ import java.io.InputStreamReader;
|
|||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.charset.UnsupportedCharsetException;
|
import java.nio.charset.UnsupportedCharsetException;
|
||||||
@ -83,6 +84,7 @@ import org.eclipse.jetty.server.session.Session;
|
|||||||
import org.eclipse.jetty.server.session.SessionHandler;
|
import org.eclipse.jetty.server.session.SessionHandler;
|
||||||
import org.eclipse.jetty.util.Attributes;
|
import org.eclipse.jetty.util.Attributes;
|
||||||
import org.eclipse.jetty.util.AttributesMap;
|
import org.eclipse.jetty.util.AttributesMap;
|
||||||
|
import org.eclipse.jetty.util.HostPort;
|
||||||
import org.eclipse.jetty.util.IO;
|
import org.eclipse.jetty.util.IO;
|
||||||
import org.eclipse.jetty.util.MultiMap;
|
import org.eclipse.jetty.util.MultiMap;
|
||||||
import org.eclipse.jetty.util.StringUtil;
|
import org.eclipse.jetty.util.StringUtil;
|
||||||
@ -984,11 +986,12 @@ 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 name;
|
return HostPort.normalizeHost(name);
|
||||||
}
|
}
|
||||||
catch (java.net.UnknownHostException e)
|
catch (UnknownHostException e)
|
||||||
{
|
{
|
||||||
LOG.ignore(e);
|
LOG.ignore(e);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -996,9 +999,10 @@ public class Request implements HttpServletRequest
|
|||||||
if (local == null)
|
if (local == null)
|
||||||
return "";
|
return "";
|
||||||
InetAddress address = local.getAddress();
|
InetAddress address = local.getAddress();
|
||||||
if (address == null)
|
String result = address == null
|
||||||
return local.getHostString();
|
? local.getHostString()
|
||||||
return address.getHostAddress();
|
: address.getHostAddress();
|
||||||
|
return HostPort.normalizeHost(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1011,7 +1015,7 @@ public class Request implements HttpServletRequest
|
|||||||
{
|
{
|
||||||
InetSocketAddress local = _channel.getLocalAddress();
|
InetSocketAddress local = _channel.getLocalAddress();
|
||||||
if (local != null)
|
if (local != null)
|
||||||
return local.getHostString();
|
return HostPort.normalizeHost(local.getHostString());
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -1019,9 +1023,9 @@ 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 name;
|
return HostPort.normalizeHost(name);
|
||||||
}
|
}
|
||||||
catch (java.net.UnknownHostException e)
|
catch (UnknownHostException e)
|
||||||
{
|
{
|
||||||
LOG.ignore(e);
|
LOG.ignore(e);
|
||||||
}
|
}
|
||||||
@ -1236,15 +1240,17 @@ public class Request implements HttpServletRequest
|
|||||||
InetSocketAddress remote = _remote;
|
InetSocketAddress remote = _remote;
|
||||||
if (remote == null)
|
if (remote == null)
|
||||||
remote = _channel.getRemoteAddress();
|
remote = _channel.getRemoteAddress();
|
||||||
|
|
||||||
if (remote == null)
|
if (remote == null)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
InetAddress address = remote.getAddress();
|
InetAddress address = remote.getAddress();
|
||||||
if (address == null)
|
String result = address == null
|
||||||
return remote.getHostString();
|
? remote.getHostString()
|
||||||
|
: address.getHostAddress();
|
||||||
return 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1256,7 +1262,10 @@ public class Request implements HttpServletRequest
|
|||||||
InetSocketAddress remote = _remote;
|
InetSocketAddress remote = _remote;
|
||||||
if (remote == null)
|
if (remote == null)
|
||||||
remote = _channel.getRemoteAddress();
|
remote = _channel.getRemoteAddress();
|
||||||
return remote == null ? "" : remote.getHostString();
|
if (remote == null)
|
||||||
|
return "";
|
||||||
|
// We want the URI host, so add IPv6 brackets if necessary.
|
||||||
|
return HostPort.normalizeHost(remote.getHostString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1411,14 +1420,14 @@ 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 name;
|
return HostPort.normalizeHost(name);
|
||||||
|
|
||||||
// Return the local host
|
// Return the local host
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return InetAddress.getLocalHost().getHostAddress();
|
return HostPort.normalizeHost(InetAddress.getLocalHost().getHostAddress());
|
||||||
}
|
}
|
||||||
catch (java.net.UnknownHostException e)
|
catch (UnknownHostException e)
|
||||||
{
|
{
|
||||||
LOG.ignore(e);
|
LOG.ignore(e);
|
||||||
}
|
}
|
||||||
|
@ -703,7 +703,7 @@ public class ForwardedRequestCustomizerTest
|
|||||||
public void accept(Actual actual)
|
public void accept(Actual actual)
|
||||||
{
|
{
|
||||||
assertThat("scheme", actual.scheme.get(), is(expectedScheme));
|
assertThat("scheme", actual.scheme.get(), is(expectedScheme));
|
||||||
if (actual.scheme.equals("https"))
|
if (actual.scheme.get().equals("https"))
|
||||||
{
|
{
|
||||||
assertTrue(actual.wasSecure.get(), "wasSecure");
|
assertTrue(actual.wasSecure.get(), "wasSecure");
|
||||||
}
|
}
|
||||||
|
@ -109,8 +109,8 @@ public class ProxyConnectionTest
|
|||||||
|
|
||||||
assertThat(response, Matchers.containsString("HTTP/1.1 200"));
|
assertThat(response, Matchers.containsString("HTTP/1.1 200"));
|
||||||
assertThat(response, Matchers.containsString("pathInfo=/path"));
|
assertThat(response, Matchers.containsString("pathInfo=/path"));
|
||||||
assertThat(response, Matchers.containsString("remote=eeee:eeee:eeee:eeee:eeee:eeee:eeee:eeee:65535"));
|
assertThat(response, Matchers.containsString("remote=[eeee:eeee:eeee:eeee:eeee:eeee:eeee:eeee]:65535"));
|
||||||
assertThat(response, Matchers.containsString("local=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:65535"));
|
assertThat(response, Matchers.containsString("local=[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@ -147,8 +147,8 @@ public class ProxyConnectionTest
|
|||||||
|
|
||||||
assertThat(response, Matchers.containsString("HTTP/1.1 200"));
|
assertThat(response, Matchers.containsString("HTTP/1.1 200"));
|
||||||
assertThat(response, Matchers.containsString("pathInfo=/path"));
|
assertThat(response, Matchers.containsString("pathInfo=/path"));
|
||||||
assertThat(response, Matchers.containsString("local=eeee:eeee:eeee:eeee:eeee:eeee:eeee:eeee:8080"));
|
assertThat(response, Matchers.containsString("local=[eeee:eeee:eeee:eeee:eeee:eeee:eeee:eeee]:8080"));
|
||||||
assertThat(response, Matchers.containsString("remote=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:12345"));
|
assertThat(response, Matchers.containsString("remote=[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:12345"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
|
@ -813,7 +813,7 @@ public class ResponseTest
|
|||||||
};
|
};
|
||||||
|
|
||||||
int[] ports = new int[]{8080, 80};
|
int[] ports = new int[]{8080, 80};
|
||||||
String[] hosts = new String[]{null, "myhost", "192.168.0.1", "0::1"};
|
String[] hosts = new String[]{null, "myhost", "192.168.0.1", "[0::1]"};
|
||||||
for (int port : ports)
|
for (int port : ports)
|
||||||
{
|
{
|
||||||
for (String host : hosts)
|
for (String host : hosts)
|
||||||
@ -850,7 +850,7 @@ public class ResponseTest
|
|||||||
String location = response.getHeader("Location");
|
String location = response.getHeader("Location");
|
||||||
|
|
||||||
String expected = tests[i][1]
|
String expected = tests[i][1]
|
||||||
.replace("@HOST@", host == null ? request.getLocalAddr() : (host.contains(":") ? ("[" + host + "]") : host))
|
.replace("@HOST@", host == null ? request.getLocalAddr() : host)
|
||||||
.replace("@PORT@", host == null ? ":8888" : (port == 80 ? "" : (":" + port)));
|
.replace("@PORT@", host == null ? ":8888" : (port == 80 ? "" : (":" + port)));
|
||||||
assertEquals(expected, location, "test-" + i + " " + host + ":" + port);
|
assertEquals(expected, location, "test-" + i + " " + host + ":" + port);
|
||||||
}
|
}
|
||||||
@ -887,7 +887,7 @@ public class ResponseTest
|
|||||||
};
|
};
|
||||||
|
|
||||||
int[] ports = new int[]{8080, 80};
|
int[] ports = new int[]{8080, 80};
|
||||||
String[] hosts = new String[]{null, "myhost", "192.168.0.1", "0::1"};
|
String[] hosts = new String[]{null, "myhost", "192.168.0.1", "[0::1]"};
|
||||||
for (int port : ports)
|
for (int port : ports)
|
||||||
{
|
{
|
||||||
for (String host : hosts)
|
for (String host : hosts)
|
||||||
@ -925,7 +925,7 @@ public class ResponseTest
|
|||||||
String location = response.getHeader("Location");
|
String location = response.getHeader("Location");
|
||||||
|
|
||||||
String expected = tests[i][1]
|
String expected = tests[i][1]
|
||||||
.replace("@HOST@", host == null ? request.getLocalAddr() : (host.contains(":") ? ("[" + host + "]") : host))
|
.replace("@HOST@", host == null ? request.getLocalAddr() : host)
|
||||||
.replace("@PORT@", host == null ? ":8888" : (port == 80 ? "" : (":" + port)));
|
.replace("@PORT@", host == null ? ":8888" : (port == 80 ? "" : (":" + port)));
|
||||||
assertEquals(expected, location, "test-" + i + " " + host + ":" + port);
|
assertEquals(expected, location, "test-" + i + " " + host + ":" + port);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
|
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
|
||||||
org.eclipse.jetty.LEVEL=INFO
|
|
||||||
#org.eclipse.jetty.LEVEL=DEBUG
|
#org.eclipse.jetty.LEVEL=DEBUG
|
||||||
#org.eclipse.jetty.server.LEVEL=DEBUG
|
#org.eclipse.jetty.server.LEVEL=DEBUG
|
||||||
#org.eclipse.jetty.servlet.LEVEL=DEBUG
|
#org.eclipse.jetty.servlet.LEVEL=DEBUG
|
||||||
#org.eclipse.jetty.io.ChannelEndPoint.LEVEL=DEBUG
|
#org.eclipse.jetty.io.ChannelEndPoint.LEVEL=DEBUG
|
||||||
#org.eclipse.jetty.server.DebugListener.LEVEL=DEBUG
|
#org.eclipse.jetty.server.DebugListener.LEVEL=DEBUG
|
||||||
#org.eclipse.jetty.server.HttpChannelState.LEVEL=DEBUG
|
#org.eclipse.jetty.server.HttpChannelState.LEVEL=DEBUG
|
||||||
|
@ -1369,12 +1369,10 @@ public class DoSFilter implements Filter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String createRemotePortId(final ServletRequest request)
|
private String createRemotePortId(ServletRequest request)
|
||||||
{
|
{
|
||||||
final String addr = request.getRemoteAddr();
|
String addr = request.getRemoteAddr();
|
||||||
final int port = request.getRemotePort();
|
int port = request.getRemotePort();
|
||||||
if (addr.contains(":"))
|
|
||||||
return "[" + addr + "]:" + port;
|
|
||||||
return addr + ":" + port;
|
return addr + ":" + port;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,22 +19,18 @@
|
|||||||
package org.eclipse.jetty.util;
|
package org.eclipse.jetty.util;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse an authority string into Host and Port
|
* <p>Parse an authority string (in the form {@code host:port}) into
|
||||||
* <p>Parse a string in the form "host:port", handling IPv4 an IPv6 hosts</p>
|
* {@code host} and {@code port}, handling IPv4 and IPv6 host formats
|
||||||
*
|
* as defined in https://www.ietf.org/rfc/rfc2732.txt</p>
|
||||||
* <p>The System property "org.eclipse.jetty.util.HostPort.STRIP_IPV6" can be set to a boolean
|
|
||||||
* value to control of the square brackets are stripped off IPv6 addresses (default false).</p>
|
|
||||||
*/
|
*/
|
||||||
public class HostPort
|
public class HostPort
|
||||||
{
|
{
|
||||||
private static final boolean STRIP_IPV6 = Boolean.parseBoolean(System.getProperty("org.eclipse.jetty.util.HostPort.STRIP_IPV6", "false"));
|
|
||||||
|
|
||||||
private final String _host;
|
private final String _host;
|
||||||
private final int _port;
|
private final int _port;
|
||||||
|
|
||||||
public HostPort(String host, int port)
|
public HostPort(String host, int port)
|
||||||
{
|
{
|
||||||
_host = host;
|
_host = normalizeHost(host);
|
||||||
_port = port;
|
_port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,7 +51,7 @@ public class HostPort
|
|||||||
int close = authority.lastIndexOf(']');
|
int close = authority.lastIndexOf(']');
|
||||||
if (close < 0)
|
if (close < 0)
|
||||||
throw new IllegalArgumentException("Bad IPv6 host");
|
throw new IllegalArgumentException("Bad IPv6 host");
|
||||||
_host = STRIP_IPV6 ? authority.substring(1, close) : authority.substring(0, close + 1);
|
_host = authority.substring(0, close + 1);
|
||||||
|
|
||||||
if (authority.length() > close + 1)
|
if (authority.length() > close + 1)
|
||||||
{
|
{
|
||||||
@ -64,14 +60,17 @@ public class HostPort
|
|||||||
_port = parsePort(authority.substring(close + 2));
|
_port = parsePort(authority.substring(close + 2));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
_port = 0;
|
_port = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// ipv4address or hostname
|
// ipv6address or ipv4address or hostname
|
||||||
int c = authority.lastIndexOf(':');
|
int c = authority.lastIndexOf(':');
|
||||||
if (c >= 0)
|
if (c >= 0)
|
||||||
{
|
{
|
||||||
|
// ipv6address
|
||||||
if (c != authority.indexOf(':'))
|
if (c != authority.indexOf(':'))
|
||||||
{
|
{
|
||||||
_host = "[" + authority + "]";
|
_host = "[" + authority + "]";
|
||||||
@ -94,14 +93,9 @@ public class HostPort
|
|||||||
{
|
{
|
||||||
throw iae;
|
throw iae;
|
||||||
}
|
}
|
||||||
catch (final Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
throw new IllegalArgumentException("Bad HostPort")
|
throw new IllegalArgumentException("Bad HostPort", ex);
|
||||||
{
|
|
||||||
{
|
|
||||||
initCause(ex);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +120,7 @@ public class HostPort
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the port.
|
* Get the port or the given default port.
|
||||||
*
|
*
|
||||||
* @param defaultPort, the default port to return if a port is not specified
|
* @param defaultPort, the default port to return if a port is not specified
|
||||||
* @return the port
|
* @return the port
|
||||||
@ -140,15 +134,17 @@ public class HostPort
|
|||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
if (_port > 0)
|
if (_port > 0)
|
||||||
return normalizeHost(_host) + ":" + _port;
|
return _host + ":" + _port;
|
||||||
return _host;
|
return _host;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalize IPv6 address as per https://www.ietf.org/rfc/rfc2732.txt
|
* Normalizes IPv6 address as per https://tools.ietf.org/html/rfc2732
|
||||||
|
* and https://tools.ietf.org/html/rfc6874,
|
||||||
|
* surrounding with square brackets if they are absent.
|
||||||
*
|
*
|
||||||
* @param host A host name
|
* @param host a host name, IPv4 address, IPv6 address or IPv6 literal
|
||||||
* @return Host name surrounded by '[' and ']' as needed.
|
* @return a host name or an IPv4 address or an IPv6 literal (not an IPv6 address)
|
||||||
*/
|
*/
|
||||||
public static String normalizeHost(String host)
|
public static String normalizeHost(String host)
|
||||||
{
|
{
|
||||||
@ -165,7 +161,7 @@ public class HostPort
|
|||||||
*
|
*
|
||||||
* @param rawPort the port string.
|
* @param rawPort the port string.
|
||||||
* @return the integer value for the port.
|
* @return the integer value for the port.
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException if the port is invalid
|
||||||
*/
|
*/
|
||||||
public static int parsePort(String rawPort) throws IllegalArgumentException
|
public static int parsePort(String rawPort) throws IllegalArgumentException
|
||||||
{
|
{
|
||||||
|
@ -21,6 +21,7 @@ package org.eclipse.jetty.http.client;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InterruptedIOException;
|
import java.io.InterruptedIOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
@ -47,10 +48,12 @@ import org.eclipse.jetty.http.HttpStatus;
|
|||||||
import org.eclipse.jetty.http2.FlowControlStrategy;
|
import org.eclipse.jetty.http2.FlowControlStrategy;
|
||||||
import org.eclipse.jetty.server.Request;
|
import org.eclipse.jetty.server.Request;
|
||||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||||
|
import org.eclipse.jetty.toolchain.test.Net;
|
||||||
import org.eclipse.jetty.util.Callback;
|
import org.eclipse.jetty.util.Callback;
|
||||||
import org.eclipse.jetty.util.IO;
|
import org.eclipse.jetty.util.IO;
|
||||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||||
|
import org.hamcrest.Matchers;
|
||||||
import org.junit.jupiter.api.Assumptions;
|
import org.junit.jupiter.api.Assumptions;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
import org.junit.jupiter.params.provider.ArgumentsSource;
|
import org.junit.jupiter.params.provider.ArgumentsSource;
|
||||||
@ -60,6 +63,7 @@ import static org.hamcrest.Matchers.containsString;
|
|||||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.junit.jupiter.api.Assertions.fail;
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
@ -676,6 +680,59 @@ public class HttpClientTest extends AbstractTest<TransportScenario>
|
|||||||
assertEquals(users, destinations.size());
|
assertEquals(users, destinations.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ArgumentsSource(TransportProvider.class)
|
||||||
|
public void testIPv6Host(Transport transport) throws Exception
|
||||||
|
{
|
||||||
|
Assumptions.assumeTrue(Net.isIpv6InterfaceAvailable());
|
||||||
|
|
||||||
|
init(transport);
|
||||||
|
scenario.start(new EmptyServerHandler()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException
|
||||||
|
{
|
||||||
|
response.setContentType("text/plain");
|
||||||
|
response.getOutputStream().print(request.getHeader("Host"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test with a full URI.
|
||||||
|
String hostAddress = "::1";
|
||||||
|
String host = "[" + hostAddress + "]";
|
||||||
|
int port = Integer.parseInt(scenario.getNetworkConnectorLocalPort().get());
|
||||||
|
String uri = scenario.getScheme() + "://" + host + ":" + port + "/path";
|
||||||
|
ContentResponse response = scenario.client.newRequest(uri)
|
||||||
|
.method(HttpMethod.PUT)
|
||||||
|
.timeout(5, TimeUnit.SECONDS)
|
||||||
|
.send();
|
||||||
|
assertNotNull(response);
|
||||||
|
assertEquals(200, response.getStatus());
|
||||||
|
assertThat(new String(response.getContent(), StandardCharsets.ISO_8859_1), Matchers.startsWith("[::1]:"));
|
||||||
|
|
||||||
|
// Test with host address.
|
||||||
|
response = scenario.client.newRequest(hostAddress, port)
|
||||||
|
.scheme(scenario.getScheme())
|
||||||
|
.method(HttpMethod.PUT)
|
||||||
|
.timeout(5, TimeUnit.SECONDS)
|
||||||
|
.send();
|
||||||
|
assertNotNull(response);
|
||||||
|
assertEquals(200, response.getStatus());
|
||||||
|
assertThat(new String(response.getContent(), StandardCharsets.ISO_8859_1), Matchers.startsWith("[::1]:"));
|
||||||
|
|
||||||
|
// Test with host.
|
||||||
|
response = scenario.client.newRequest(host, port)
|
||||||
|
.scheme(scenario.getScheme())
|
||||||
|
.method(HttpMethod.PUT)
|
||||||
|
.timeout(5, TimeUnit.SECONDS)
|
||||||
|
.send();
|
||||||
|
assertNotNull(response);
|
||||||
|
assertEquals(200, response.getStatus());
|
||||||
|
assertThat(new String(response.getContent(), StandardCharsets.ISO_8859_1), Matchers.startsWith("[::1]:"));
|
||||||
|
|
||||||
|
assertEquals(1, scenario.client.getDestinations().size());
|
||||||
|
}
|
||||||
|
|
||||||
private void sleep(long time) throws IOException
|
private void sleep(long time) throws IOException
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
Loading…
x
Reference in New Issue
Block a user