Merged branch 'jetty-9.4.x' into 'jetty-10.0.x'.
This commit is contained in:
commit
6430177685
|
@ -1106,11 +1106,26 @@ public class HttpClient extends ContainerLifeCycle
|
||||||
return HttpScheme.HTTPS.is(scheme) || HttpScheme.WSS.is(scheme);
|
return HttpScheme.HTTPS.is(scheme) || HttpScheme.WSS.is(scheme);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@code SslClientConnectionFactory} wrapping the given connection factory.
|
||||||
|
*
|
||||||
|
* @param connectionFactory the connection factory to wrap
|
||||||
|
* @return a new SslClientConnectionFactory
|
||||||
|
* @deprecated use {@link #newSslClientConnectionFactory(SslContextFactory, ClientConnectionFactory)} instead
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
protected ClientConnectionFactory newSslClientConnectionFactory(ClientConnectionFactory connectionFactory)
|
protected ClientConnectionFactory newSslClientConnectionFactory(ClientConnectionFactory connectionFactory)
|
||||||
{
|
{
|
||||||
return new SslClientConnectionFactory(getSslContextFactory(), getByteBufferPool(), getExecutor(), connectionFactory);
|
return new SslClientConnectionFactory(getSslContextFactory(), getByteBufferPool(), getExecutor(), connectionFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected ClientConnectionFactory newSslClientConnectionFactory(SslContextFactory sslContextFactory, ClientConnectionFactory connectionFactory)
|
||||||
|
{
|
||||||
|
if (sslContextFactory == null)
|
||||||
|
return newSslClientConnectionFactory(connectionFactory);
|
||||||
|
return new SslClientConnectionFactory(sslContextFactory, getByteBufferPool(), getExecutor(), connectionFactory);
|
||||||
|
}
|
||||||
|
|
||||||
private class ContentDecoderFactorySet implements Set<ContentDecoder.Factory>
|
private class ContentDecoderFactorySet implements Set<ContentDecoder.Factory>
|
||||||
{
|
{
|
||||||
private final Set<ContentDecoder.Factory> set = new HashSet<>();
|
private final Set<ContentDecoder.Factory> set = new HashSet<>();
|
||||||
|
|
|
@ -53,6 +53,7 @@ import org.eclipse.jetty.util.component.Dumpable;
|
||||||
import org.eclipse.jetty.util.component.DumpableCollection;
|
import org.eclipse.jetty.util.component.DumpableCollection;
|
||||||
import org.eclipse.jetty.util.log.Log;
|
import org.eclipse.jetty.util.log.Log;
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
|
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||||
import org.eclipse.jetty.util.thread.Scheduler;
|
import org.eclipse.jetty.util.thread.Scheduler;
|
||||||
import org.eclipse.jetty.util.thread.Sweeper;
|
import org.eclipse.jetty.util.thread.Sweeper;
|
||||||
|
|
||||||
|
@ -108,12 +109,12 @@ public class HttpDestination extends ContainerLifeCycle implements Destination,
|
||||||
{
|
{
|
||||||
connectionFactory = proxy.newClientConnectionFactory(connectionFactory);
|
connectionFactory = proxy.newClientConnectionFactory(connectionFactory);
|
||||||
if (proxy.isSecure())
|
if (proxy.isSecure())
|
||||||
connectionFactory = newSslClientConnectionFactory(connectionFactory);
|
connectionFactory = newSslClientConnectionFactory(proxy.getSslContextFactory(), connectionFactory);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (isSecure())
|
if (isSecure())
|
||||||
connectionFactory = newSslClientConnectionFactory(connectionFactory);
|
connectionFactory = newSslClientConnectionFactory(null, connectionFactory);
|
||||||
}
|
}
|
||||||
return connectionFactory;
|
return connectionFactory;
|
||||||
}
|
}
|
||||||
|
@ -149,9 +150,9 @@ public class HttpDestination extends ContainerLifeCycle implements Destination,
|
||||||
return new BlockingArrayQueue<>(client.getMaxRequestsQueuedPerDestination());
|
return new BlockingArrayQueue<>(client.getMaxRequestsQueuedPerDestination());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ClientConnectionFactory newSslClientConnectionFactory(ClientConnectionFactory connectionFactory)
|
protected ClientConnectionFactory newSslClientConnectionFactory(SslContextFactory sslContextFactory, ClientConnectionFactory connectionFactory)
|
||||||
{
|
{
|
||||||
return client.newSslClientConnectionFactory(connectionFactory);
|
return client.newSslClientConnectionFactory(sslContextFactory, connectionFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSecure()
|
public boolean isSecure()
|
||||||
|
|
|
@ -60,6 +60,16 @@ public class HttpProxy extends ProxyConfiguration.Proxy
|
||||||
super(address, secure, Objects.requireNonNull(protocol));
|
super(address, secure, Objects.requireNonNull(protocol));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HttpProxy(Origin.Address address, SslContextFactory.Client sslContextFactory)
|
||||||
|
{
|
||||||
|
super(address, sslContextFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpProxy(Origin.Address address, SslContextFactory.Client sslContextFactory, HttpDestination.Protocol protocol)
|
||||||
|
{
|
||||||
|
super(address, sslContextFactory, Objects.requireNonNull(protocol));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClientConnectionFactory newClientConnectionFactory(ClientConnectionFactory connectionFactory)
|
public ClientConnectionFactory newClientConnectionFactory(ClientConnectionFactory connectionFactory)
|
||||||
{
|
{
|
||||||
|
@ -212,7 +222,7 @@ public class HttpProxy extends ProxyConfiguration.Proxy
|
||||||
// Don't want to do DNS resolution here.
|
// Don't want to do DNS resolution here.
|
||||||
InetSocketAddress address = InetSocketAddress.createUnresolved(destination.getHost(), destination.getPort());
|
InetSocketAddress address = InetSocketAddress.createUnresolved(destination.getHost(), destination.getPort());
|
||||||
context.put(ClientConnector.REMOTE_SOCKET_ADDRESS_CONTEXT_KEY, address);
|
context.put(ClientConnector.REMOTE_SOCKET_ADDRESS_CONTEXT_KEY, address);
|
||||||
connectionFactory = destination.newSslClientConnectionFactory(connectionFactory);
|
connectionFactory = destination.newSslClientConnectionFactory(null, connectionFactory);
|
||||||
}
|
}
|
||||||
var oldConnection = endPoint.getConnection();
|
var oldConnection = endPoint.getConnection();
|
||||||
var newConnection = connectionFactory.newConnection(endPoint, context);
|
var newConnection = connectionFactory.newConnection(endPoint, context);
|
||||||
|
|
|
@ -22,10 +22,12 @@ import java.net.URI;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.eclipse.jetty.io.ClientConnectionFactory;
|
import org.eclipse.jetty.io.ClientConnectionFactory;
|
||||||
import org.eclipse.jetty.util.HostPort;
|
import org.eclipse.jetty.util.HostPort;
|
||||||
|
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The configuration of the forward proxy to use with {@link org.eclipse.jetty.client.HttpClient}.
|
* The configuration of the forward proxy to use with {@link org.eclipse.jetty.client.HttpClient}.
|
||||||
|
@ -64,12 +66,24 @@ public class ProxyConfiguration
|
||||||
private final Set<String> excluded = new HashSet<>();
|
private final Set<String> excluded = new HashSet<>();
|
||||||
private final Origin.Address address;
|
private final Origin.Address address;
|
||||||
private final boolean secure;
|
private final boolean secure;
|
||||||
|
private final SslContextFactory.Client sslContextFactory;
|
||||||
private final HttpDestination.Protocol protocol;
|
private final HttpDestination.Protocol protocol;
|
||||||
|
|
||||||
protected Proxy(Origin.Address address, boolean secure, HttpDestination.Protocol protocol)
|
protected Proxy(Origin.Address address, boolean secure)
|
||||||
|
{
|
||||||
|
this(address, secure, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Proxy(Origin.Address address, SslContextFactory.Client sslContextFactory)
|
||||||
|
{
|
||||||
|
this(address, true, Objects.requireNonNull(sslContextFactory));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Proxy(Origin.Address address, boolean secure, SslContextFactory.Client sslContextFactory)
|
||||||
{
|
{
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.secure = secure;
|
this.secure = secure;
|
||||||
|
this.sslContextFactory = sslContextFactory;
|
||||||
this.protocol = protocol;
|
this.protocol = protocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,6 +103,14 @@ public class ProxyConfiguration
|
||||||
return secure;
|
return secure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the optional SslContextFactory to use when connecting to proxies
|
||||||
|
*/
|
||||||
|
public SslContextFactory.Client getSslContextFactory()
|
||||||
|
{
|
||||||
|
return sslContextFactory;
|
||||||
|
}
|
||||||
|
|
||||||
public HttpDestination.Protocol getProtocol()
|
public HttpDestination.Protocol getProtocol()
|
||||||
{
|
{
|
||||||
return protocol;
|
return protocol;
|
||||||
|
|
|
@ -197,7 +197,7 @@ public class Socks4Proxy extends ProxyConfiguration.Proxy
|
||||||
HttpDestination destination = (HttpDestination)context.get(HttpClientTransport.HTTP_DESTINATION_CONTEXT_KEY);
|
HttpDestination destination = (HttpDestination)context.get(HttpClientTransport.HTTP_DESTINATION_CONTEXT_KEY);
|
||||||
ClientConnectionFactory connectionFactory = this.connectionFactory;
|
ClientConnectionFactory connectionFactory = this.connectionFactory;
|
||||||
if (destination.isSecure())
|
if (destination.isSecure())
|
||||||
connectionFactory = destination.newSslClientConnectionFactory(connectionFactory);
|
connectionFactory = destination.newSslClientConnectionFactory(null, connectionFactory);
|
||||||
org.eclipse.jetty.io.Connection newConnection = connectionFactory.newConnection(getEndPoint(), context);
|
org.eclipse.jetty.io.Connection newConnection = connectionFactory.newConnection(getEndPoint(), context);
|
||||||
getEndPoint().upgrade(newConnection);
|
getEndPoint().upgrade(newConnection);
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
|
|
|
@ -482,9 +482,9 @@ public class HttpClientTLSTest
|
||||||
client = new HttpClient(new HttpClientTransportOverHTTP(clientConnector))
|
client = new HttpClient(new HttpClientTransportOverHTTP(clientConnector))
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
protected ClientConnectionFactory newSslClientConnectionFactory(ClientConnectionFactory connectionFactory)
|
protected ClientConnectionFactory newSslClientConnectionFactory(SslContextFactory sslContextFactory, ClientConnectionFactory connectionFactory)
|
||||||
{
|
{
|
||||||
SslClientConnectionFactory ssl = (SslClientConnectionFactory)super.newSslClientConnectionFactory(connectionFactory);
|
SslClientConnectionFactory ssl = (SslClientConnectionFactory)super.newSslClientConnectionFactory(sslContextFactory, connectionFactory);
|
||||||
ssl.setAllowMissingCloseMessage(false);
|
ssl.setAllowMissingCloseMessage(false);
|
||||||
return ssl;
|
return ssl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -703,6 +703,74 @@ public class ForwardProxyTLSServerTest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBothProxyAndServerNeedClientAuthWithDifferentKeyStores() throws Exception
|
||||||
|
{
|
||||||
|
SslContextFactory.Server serverTLS = newServerSslContextFactory();
|
||||||
|
serverTLS.setEndpointIdentificationAlgorithm(null);
|
||||||
|
serverTLS.setNeedClientAuth(true);
|
||||||
|
startTLSServer(serverTLS, new ServerHandler());
|
||||||
|
int serverPort = serverConnector.getLocalPort();
|
||||||
|
|
||||||
|
SslContextFactory.Server proxyServerTLS = newProxySslContextFactory();
|
||||||
|
proxyServerTLS.setEndpointIdentificationAlgorithm(null);
|
||||||
|
proxyServerTLS.setNeedClientAuth(true);
|
||||||
|
startProxy(proxyServerTLS);
|
||||||
|
int proxyPort = proxyConnector.getLocalPort();
|
||||||
|
|
||||||
|
SslContextFactory.Client clientTLS = new SslContextFactory.Client()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public SSLEngine newSSLEngine(String host, int port)
|
||||||
|
{
|
||||||
|
if (port != serverPort)
|
||||||
|
throw new IllegalStateException();
|
||||||
|
return super.newSSLEngine(host, port);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
clientTLS.setKeyStorePath(MavenTestingUtils.getTestResourceFile("client_server_keystore.p12").getAbsolutePath());
|
||||||
|
clientTLS.setKeyStorePassword("storepwd");
|
||||||
|
clientTLS.setEndpointIdentificationAlgorithm(null);
|
||||||
|
HttpClient httpClient = new HttpClient(clientTLS);
|
||||||
|
|
||||||
|
SslContextFactory.Client proxyClientTLS = new SslContextFactory.Client()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public SSLEngine newSSLEngine(String host, int port)
|
||||||
|
{
|
||||||
|
if (port != proxyPort)
|
||||||
|
throw new IllegalStateException();
|
||||||
|
return super.newSSLEngine(host, port);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
proxyClientTLS.setKeyStorePath(MavenTestingUtils.getTestResourceFile("client_proxy_keystore.p12").getAbsolutePath());
|
||||||
|
proxyClientTLS.setKeyStorePassword("storepwd");
|
||||||
|
proxyClientTLS.setEndpointIdentificationAlgorithm(null);
|
||||||
|
proxyClientTLS.start();
|
||||||
|
HttpProxy httpProxy = new HttpProxy(new Origin.Address("localhost", proxyConnector.getLocalPort()), proxyClientTLS);
|
||||||
|
httpClient.getProxyConfiguration().getProxies().add(httpProxy);
|
||||||
|
httpClient.start();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String body = "BODY";
|
||||||
|
ContentResponse response = httpClient.newRequest("localhost", serverConnector.getLocalPort())
|
||||||
|
.scheme(HttpScheme.HTTPS.asString())
|
||||||
|
.method(HttpMethod.GET)
|
||||||
|
.path("/echo?body=" + URLEncoder.encode(body, "UTF-8"))
|
||||||
|
.timeout(5, TimeUnit.SECONDS)
|
||||||
|
.send();
|
||||||
|
|
||||||
|
assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||||
|
String content = response.getContentAsString();
|
||||||
|
assertEquals(body, content);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
httpClient.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Tag("external")
|
@Tag("external")
|
||||||
@Disabled
|
@Disabled
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -252,9 +252,11 @@ public class HttpClientTimeoutTest extends AbstractTest<TransportScenario>
|
||||||
scenario.client = new HttpClient(scenario.provideClientTransport(transport, sslContextFactory))
|
scenario.client = new HttpClient(scenario.provideClientTransport(transport, sslContextFactory))
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public ClientConnectionFactory newSslClientConnectionFactory(ClientConnectionFactory connectionFactory)
|
public ClientConnectionFactory newSslClientConnectionFactory(SslContextFactory sslContextFactory, ClientConnectionFactory connectionFactory)
|
||||||
{
|
{
|
||||||
return new SslClientConnectionFactory(getSslContextFactory(), getByteBufferPool(), getExecutor(), connectionFactory)
|
if (sslContextFactory == null)
|
||||||
|
sslContextFactory = getSslContextFactory();
|
||||||
|
return new SslClientConnectionFactory(sslContextFactory, getByteBufferPool(), getExecutor(), connectionFactory)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
protected SslConnection newSslConnection(ByteBufferPool byteBufferPool, Executor executor, EndPoint endPoint, SSLEngine engine)
|
protected SslConnection newSslConnection(ByteBufferPool byteBufferPool, Executor executor, EndPoint endPoint, SSLEngine engine)
|
||||||
|
|
Loading…
Reference in New Issue