Internal connection operators to make use of the target name from the request URI authority
This commit is contained in:
parent
91ab690e50
commit
e6e873d88b
|
@ -95,12 +95,12 @@ class InternalH2AsyncExecRuntime implements AsyncExecRuntime {
|
|||
if (log.isDebugEnabled()) {
|
||||
log.debug("{} acquiring endpoint ({})", id, connectTimeout);
|
||||
}
|
||||
return Operations.cancellable(connPool.getSession(target, connectTimeout,
|
||||
return Operations.cancellable(connPool.getSession(route, connectTimeout,
|
||||
new FutureCallback<IOSession>() {
|
||||
|
||||
@Override
|
||||
public void completed(final IOSession ioSession) {
|
||||
sessionRef.set(new Endpoint(target, ioSession));
|
||||
sessionRef.set(new Endpoint(route, ioSession));
|
||||
reusable = true;
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("{} acquired endpoint", id);
|
||||
|
@ -184,19 +184,19 @@ class InternalH2AsyncExecRuntime implements AsyncExecRuntime {
|
|||
callback.completed(this);
|
||||
return Operations.nonCancellable();
|
||||
}
|
||||
final HttpHost target = endpoint.target;
|
||||
final HttpRoute route = endpoint.route;
|
||||
final RequestConfig requestConfig = context.getRequestConfig();
|
||||
@SuppressWarnings("deprecation")
|
||||
final Timeout connectTimeout = requestConfig.getConnectTimeout();
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("{} connecting endpoint ({})", ConnPoolSupport.getId(endpoint), connectTimeout);
|
||||
}
|
||||
return Operations.cancellable(connPool.getSession(target, connectTimeout,
|
||||
return Operations.cancellable(connPool.getSession(route, connectTimeout,
|
||||
new FutureCallback<IOSession>() {
|
||||
|
||||
@Override
|
||||
public void completed(final IOSession ioSession) {
|
||||
sessionRef.set(new Endpoint(target, ioSession));
|
||||
sessionRef.set(new Endpoint(route, ioSession));
|
||||
reusable = true;
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("{} endpoint connected", ConnPoolSupport.getId(endpoint));
|
||||
|
@ -263,15 +263,15 @@ class InternalH2AsyncExecRuntime implements AsyncExecRuntime {
|
|||
new RequestExecutionCommand(exchangeHandler, pushHandlerFactory, complexCancellable, context),
|
||||
Command.Priority.NORMAL);
|
||||
} else {
|
||||
final HttpHost target = endpoint.target;
|
||||
final HttpRoute route = endpoint.route;
|
||||
final RequestConfig requestConfig = context.getRequestConfig();
|
||||
@SuppressWarnings("deprecation")
|
||||
final Timeout connectTimeout = requestConfig.getConnectTimeout();
|
||||
connPool.getSession(target, connectTimeout, new FutureCallback<IOSession>() {
|
||||
connPool.getSession(route, connectTimeout, new FutureCallback<IOSession>() {
|
||||
|
||||
@Override
|
||||
public void completed(final IOSession ioSession) {
|
||||
sessionRef.set(new Endpoint(target, ioSession));
|
||||
sessionRef.set(new Endpoint(route, ioSession));
|
||||
reusable = true;
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("{} start execution {}", ConnPoolSupport.getId(endpoint), id);
|
||||
|
@ -309,11 +309,11 @@ class InternalH2AsyncExecRuntime implements AsyncExecRuntime {
|
|||
|
||||
static class Endpoint implements Identifiable {
|
||||
|
||||
final HttpHost target;
|
||||
final HttpRoute route;
|
||||
final IOSession session;
|
||||
|
||||
Endpoint(final HttpHost target, final IOSession session) {
|
||||
this.target = target;
|
||||
Endpoint(final HttpRoute route, final IOSession session) {
|
||||
this.route = route;
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,40 +29,49 @@ package org.apache.hc.client5.http.impl.async;
|
|||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import org.apache.hc.client5.http.HttpRoute;
|
||||
import org.apache.hc.client5.http.config.ConnectionConfig;
|
||||
import org.apache.hc.core5.concurrent.CallbackContribution;
|
||||
import org.apache.hc.core5.concurrent.FutureCallback;
|
||||
import org.apache.hc.core5.function.Callback;
|
||||
import org.apache.hc.core5.function.Resolver;
|
||||
import org.apache.hc.core5.http.HttpHost;
|
||||
import org.apache.hc.core5.http.URIScheme;
|
||||
import org.apache.hc.core5.http.nio.command.ShutdownCommand;
|
||||
import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
|
||||
import org.apache.hc.core5.http2.nio.pool.H2ConnPool;
|
||||
import org.apache.hc.core5.http2.nio.command.PingCommand;
|
||||
import org.apache.hc.core5.http2.nio.support.BasicPingHandler;
|
||||
import org.apache.hc.core5.io.CloseMode;
|
||||
import org.apache.hc.core5.io.ModalCloseable;
|
||||
import org.apache.hc.core5.net.NamedEndpoint;
|
||||
import org.apache.hc.core5.reactor.AbstractIOSessionPool;
|
||||
import org.apache.hc.core5.reactor.Command;
|
||||
import org.apache.hc.core5.reactor.ConnectionInitiator;
|
||||
import org.apache.hc.core5.reactor.IOSession;
|
||||
import org.apache.hc.core5.reactor.ssl.TransportSecurityLayer;
|
||||
import org.apache.hc.core5.util.TimeValue;
|
||||
import org.apache.hc.core5.util.Timeout;
|
||||
|
||||
class InternalH2ConnPool implements ModalCloseable {
|
||||
|
||||
private final H2ConnPool connPool;
|
||||
private final SessionPool sessionPool;
|
||||
|
||||
private volatile Resolver<HttpHost, ConnectionConfig> connectionConfigResolver;
|
||||
|
||||
InternalH2ConnPool(final ConnectionInitiator connectionInitiator,
|
||||
final Resolver<HttpHost, InetSocketAddress> addressResolver,
|
||||
final TlsStrategy tlsStrategy) {
|
||||
this.connPool = new H2ConnPool(connectionInitiator, addressResolver, tlsStrategy);
|
||||
this.sessionPool = new SessionPool(connectionInitiator, addressResolver, tlsStrategy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(final CloseMode closeMode) {
|
||||
connPool.close(closeMode);
|
||||
sessionPool.close(closeMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
connPool.close();
|
||||
sessionPool.close();
|
||||
}
|
||||
|
||||
private ConnectionConfig resolveConnectionConfig(final HttpHost httpHost) {
|
||||
|
@ -72,12 +81,12 @@ class InternalH2ConnPool implements ModalCloseable {
|
|||
}
|
||||
|
||||
public Future<IOSession> getSession(
|
||||
final HttpHost endpoint,
|
||||
final HttpRoute route,
|
||||
final Timeout connectTimeout,
|
||||
final FutureCallback<IOSession> callback) {
|
||||
final ConnectionConfig connectionConfig = resolveConnectionConfig(endpoint);
|
||||
return connPool.getSession(
|
||||
endpoint,
|
||||
final ConnectionConfig connectionConfig = resolveConnectionConfig(route.getTargetHost());
|
||||
return sessionPool.getSession(
|
||||
route,
|
||||
connectTimeout != null ? connectTimeout : connectionConfig.getConnectTimeout(),
|
||||
new CallbackContribution<IOSession>(callback) {
|
||||
|
||||
|
@ -94,11 +103,113 @@ class InternalH2ConnPool implements ModalCloseable {
|
|||
}
|
||||
|
||||
public void closeIdle(final TimeValue idleTime) {
|
||||
connPool.closeIdle(idleTime);
|
||||
sessionPool.closeIdle(idleTime);
|
||||
}
|
||||
|
||||
public void setConnectionConfigResolver(final Resolver<HttpHost, ConnectionConfig> connectionConfigResolver) {
|
||||
this.connectionConfigResolver = connectionConfigResolver;
|
||||
}
|
||||
|
||||
public TimeValue getValidateAfterInactivity() {
|
||||
return sessionPool.validateAfterInactivity;
|
||||
}
|
||||
|
||||
public void setValidateAfterInactivity(final TimeValue timeValue) {
|
||||
sessionPool.validateAfterInactivity = timeValue;
|
||||
}
|
||||
|
||||
|
||||
static class SessionPool extends AbstractIOSessionPool<HttpRoute> {
|
||||
|
||||
private final ConnectionInitiator connectionInitiator;
|
||||
private final Resolver<HttpHost, InetSocketAddress> addressResolver;
|
||||
private final TlsStrategy tlsStrategy;
|
||||
|
||||
private volatile TimeValue validateAfterInactivity = TimeValue.NEG_ONE_MILLISECOND;
|
||||
|
||||
SessionPool(final ConnectionInitiator connectionInitiator,
|
||||
final Resolver<HttpHost, InetSocketAddress> addressResolver,
|
||||
final TlsStrategy tlsStrategy) {
|
||||
this.connectionInitiator = connectionInitiator;
|
||||
this.addressResolver = addressResolver;
|
||||
this.tlsStrategy = tlsStrategy;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Future<IOSession> connectSession(final HttpRoute route,
|
||||
final Timeout connectTimeout,
|
||||
final FutureCallback<IOSession> callback) {
|
||||
final HttpHost target = route.getTargetHost();
|
||||
final InetSocketAddress localAddress = route.getLocalSocketAddress();
|
||||
final InetSocketAddress remoteAddress = addressResolver.resolve(target);
|
||||
return connectionInitiator.connect(
|
||||
target,
|
||||
remoteAddress,
|
||||
localAddress,
|
||||
connectTimeout,
|
||||
null,
|
||||
new CallbackContribution<IOSession>(callback) {
|
||||
|
||||
@Override
|
||||
public void completed(final IOSession ioSession) {
|
||||
if (tlsStrategy != null
|
||||
&& URIScheme.HTTPS.same(target.getSchemeName())
|
||||
&& ioSession instanceof TransportSecurityLayer) {
|
||||
final NamedEndpoint tlsName = route.getTargetName() != null ? route.getTargetName() : target;
|
||||
tlsStrategy.upgrade(
|
||||
(TransportSecurityLayer) ioSession,
|
||||
tlsName,
|
||||
null,
|
||||
connectTimeout,
|
||||
new CallbackContribution<TransportSecurityLayer>(callback) {
|
||||
|
||||
@Override
|
||||
public void completed(final TransportSecurityLayer transportSecurityLayer) {
|
||||
callback.completed(ioSession);
|
||||
}
|
||||
|
||||
});
|
||||
ioSession.setSocketTimeout(connectTimeout);
|
||||
} else {
|
||||
callback.completed(ioSession);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateSession(final IOSession ioSession,
|
||||
final Callback<Boolean> callback) {
|
||||
if (ioSession.isOpen()) {
|
||||
final TimeValue timeValue = validateAfterInactivity;
|
||||
if (TimeValue.isNonNegative(timeValue)) {
|
||||
final long lastAccessTime = Math.min(ioSession.getLastReadTime(), ioSession.getLastWriteTime());
|
||||
final long deadline = lastAccessTime + timeValue.toMilliseconds();
|
||||
if (deadline <= System.currentTimeMillis()) {
|
||||
final Timeout socketTimeoutMillis = ioSession.getSocketTimeout();
|
||||
ioSession.enqueue(new PingCommand(new BasicPingHandler(result -> {
|
||||
ioSession.setSocketTimeout(socketTimeoutMillis);
|
||||
callback.execute(result);
|
||||
})), Command.Priority.NORMAL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
callback.execute(true);
|
||||
} else {
|
||||
callback.execute(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void closeSession(final IOSession ioSession,
|
||||
final CloseMode closeMode) {
|
||||
if (closeMode == CloseMode.GRACEFUL) {
|
||||
ioSession.enqueue(ShutdownCommand.GRACEFUL, Command.Priority.NORMAL);
|
||||
} else {
|
||||
ioSession.close(closeMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ import java.util.concurrent.Future;
|
|||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
import org.apache.hc.client5.http.DnsResolver;
|
||||
import org.apache.hc.client5.http.HttpRoute;
|
||||
import org.apache.hc.client5.http.config.Configurable;
|
||||
import org.apache.hc.client5.http.config.ConnectionConfig;
|
||||
import org.apache.hc.client5.http.config.RequestConfig;
|
||||
|
@ -141,7 +142,7 @@ public final class MinimalH2AsyncClient extends AbstractMinimalHttpAsyncClientBa
|
|||
final Timeout connectTimeout = requestConfig.getConnectTimeout();
|
||||
final HttpHost target = new HttpHost(request.getScheme(), request.getAuthority());
|
||||
|
||||
final Future<IOSession> sessionFuture = connPool.getSession(target, connectTimeout,
|
||||
final Future<IOSession> sessionFuture = connPool.getSession(new HttpRoute(target), connectTimeout,
|
||||
new FutureCallback<IOSession>() {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -477,24 +477,20 @@ public class BasicHttpClientConnectionManager implements HttpClientConnectionMan
|
|||
return;
|
||||
}
|
||||
final HttpRoute route = internalEndpoint.getRoute();
|
||||
final HttpHost host;
|
||||
if (route.getProxyHost() != null) {
|
||||
host = route.getProxyHost();
|
||||
} else {
|
||||
host = route.getTargetHost();
|
||||
}
|
||||
final HttpHost firstHop = route.getProxyHost() != null ? route.getProxyHost() : route.getTargetHost();
|
||||
final Timeout connectTimeout = timeout != null ? Timeout.of(timeout.getDuration(), timeout.getTimeUnit()) : connectionConfig.getConnectTimeout();
|
||||
final ManagedHttpClientConnection connection = internalEndpoint.getConnection();
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("{} connecting endpoint to {} ({})", ConnPoolSupport.getId(endpoint), host, connectTimeout);
|
||||
LOG.debug("{} connecting endpoint to {} ({})", ConnPoolSupport.getId(endpoint), firstHop, connectTimeout);
|
||||
}
|
||||
this.connectionOperator.connect(
|
||||
connection,
|
||||
host,
|
||||
firstHop,
|
||||
route.getTargetName(),
|
||||
route.getLocalSocketAddress(),
|
||||
connectTimeout,
|
||||
socketConfig,
|
||||
tlsConfig,
|
||||
route.isTunnelled() ? null : tlsConfig,
|
||||
context);
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("{} connected {}", ConnPoolSupport.getId(endpoint), ConnPoolSupport.getId(conn));
|
||||
|
@ -517,9 +513,11 @@ public class BasicHttpClientConnectionManager implements HttpClientConnectionMan
|
|||
Args.notNull(endpoint, "Endpoint");
|
||||
Args.notNull(route, "HTTP route");
|
||||
final InternalConnectionEndpoint internalEndpoint = cast(endpoint);
|
||||
final HttpRoute route = internalEndpoint.getRoute();
|
||||
this.connectionOperator.upgrade(
|
||||
internalEndpoint.getConnection(),
|
||||
internalEndpoint.getRoute().getTargetHost(),
|
||||
route.getTargetHost(),
|
||||
route.getTargetName(),
|
||||
tlsConfig,
|
||||
context);
|
||||
} finally {
|
||||
|
|
|
@ -58,6 +58,7 @@ import org.apache.hc.core5.http.config.Lookup;
|
|||
import org.apache.hc.core5.http.io.SocketConfig;
|
||||
import org.apache.hc.core5.http.protocol.HttpContext;
|
||||
import org.apache.hc.core5.io.Closer;
|
||||
import org.apache.hc.core5.net.NamedEndpoint;
|
||||
import org.apache.hc.core5.util.Args;
|
||||
import org.apache.hc.core5.util.TimeValue;
|
||||
import org.apache.hc.core5.util.Timeout;
|
||||
|
@ -147,52 +148,52 @@ public class DefaultHttpClientConnectionOperator implements HttpClientConnection
|
|||
final SocketConfig socketConfig,
|
||||
final HttpContext context) throws IOException {
|
||||
final Timeout timeout = connectTimeout != null ? Timeout.of(connectTimeout.getDuration(), connectTimeout.getTimeUnit()) : null;
|
||||
connect(conn, host, localAddress, timeout, socketConfig, null, context);
|
||||
connect(conn, host, null, localAddress, timeout, socketConfig, null, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(
|
||||
final ManagedHttpClientConnection conn,
|
||||
final HttpHost host,
|
||||
final HttpHost endpointHost,
|
||||
final NamedEndpoint endpointName,
|
||||
final InetSocketAddress localAddress,
|
||||
final Timeout connectTimeout,
|
||||
final SocketConfig socketConfig,
|
||||
final Object attachment,
|
||||
final HttpContext context) throws IOException {
|
||||
Args.notNull(conn, "Connection");
|
||||
Args.notNull(host, "Host");
|
||||
Args.notNull(endpointHost, "Host");
|
||||
Args.notNull(socketConfig, "Socket config");
|
||||
Args.notNull(context, "Context");
|
||||
final InetAddress[] remoteAddresses;
|
||||
if (host.getAddress() != null) {
|
||||
remoteAddresses = new InetAddress[] { host.getAddress() };
|
||||
if (endpointHost.getAddress() != null) {
|
||||
remoteAddresses = new InetAddress[] { endpointHost.getAddress() };
|
||||
} else {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("{} resolving remote address", host.getHostName());
|
||||
LOG.debug("{} resolving remote address", endpointHost.getHostName());
|
||||
}
|
||||
|
||||
remoteAddresses = this.dnsResolver.resolve(host.getHostName());
|
||||
remoteAddresses = this.dnsResolver.resolve(endpointHost.getHostName());
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("{} resolved to {}", host.getHostName(), remoteAddresses == null ? "null" : Arrays.asList(remoteAddresses));
|
||||
LOG.debug("{} resolved to {}", endpointHost.getHostName(), remoteAddresses == null ? "null" : Arrays.asList(remoteAddresses));
|
||||
}
|
||||
|
||||
if (remoteAddresses == null || remoteAddresses.length == 0) {
|
||||
throw new UnknownHostException(host.getHostName());
|
||||
throw new UnknownHostException(endpointHost.getHostName());
|
||||
}
|
||||
}
|
||||
|
||||
final Timeout soTimeout = socketConfig.getSoTimeout();
|
||||
final SocketAddress socksProxyAddress = socketConfig.getSocksProxyAddress();
|
||||
final Proxy socksProxy = socksProxyAddress != null ? new Proxy(Proxy.Type.SOCKS, socksProxyAddress) : null;
|
||||
final int port = this.schemePortResolver.resolve(host.getSchemeName(), host);
|
||||
final int port = this.schemePortResolver.resolve(endpointHost.getSchemeName(), endpointHost);
|
||||
for (int i = 0; i < remoteAddresses.length; i++) {
|
||||
final InetAddress address = remoteAddresses[i];
|
||||
final boolean last = i == remoteAddresses.length - 1;
|
||||
final InetSocketAddress remoteAddress = new InetSocketAddress(address, port);
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("{}:{} connecting {}->{} ({})",
|
||||
host.getHostName(), host.getPort(), localAddress, remoteAddress, connectTimeout);
|
||||
LOG.debug("{} connecting {}->{} ({})", endpointHost, localAddress, remoteAddress, connectTimeout);
|
||||
}
|
||||
final Socket socket = detachedSocketFactory.create(socksProxy);
|
||||
try {
|
||||
|
@ -220,14 +221,18 @@ public class DefaultHttpClientConnectionOperator implements HttpClientConnection
|
|||
}
|
||||
socket.connect(remoteAddress, TimeValue.isPositive(connectTimeout) ? connectTimeout.toMillisecondsIntBound() : 0);
|
||||
conn.bind(socket);
|
||||
conn.setSocketTimeout(soTimeout);
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("{}:{} connected {}->{} as {}",
|
||||
host.getHostName(), host.getPort(), localAddress, remoteAddress, ConnPoolSupport.getId(conn));
|
||||
LOG.debug("{} {} connected {}->{}", ConnPoolSupport.getId(conn), endpointHost,
|
||||
conn.getLocalAddress(), conn.getRemoteAddress());
|
||||
}
|
||||
final TlsSocketStrategy tlsSocketStrategy = tlsSocketStrategyLookup != null ? tlsSocketStrategyLookup.lookup(host.getSchemeName()) : null;
|
||||
conn.setSocketTimeout(soTimeout);
|
||||
final TlsSocketStrategy tlsSocketStrategy = tlsSocketStrategyLookup != null ? tlsSocketStrategyLookup.lookup(endpointHost.getSchemeName()) : null;
|
||||
if (tlsSocketStrategy != null) {
|
||||
final Socket upgradedSocket = tlsSocketStrategy.upgrade(socket, host.getHostName(), port, attachment, context);
|
||||
final NamedEndpoint tlsName = endpointName != null ? endpointName : endpointHost;
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("{} {} upgrading to TLS", ConnPoolSupport.getId(conn), tlsName);
|
||||
}
|
||||
final Socket upgradedSocket = tlsSocketStrategy.upgrade(socket, tlsName.getHostName(), tlsName.getPort(), attachment, context);
|
||||
conn.bind(upgradedSocket);
|
||||
}
|
||||
return;
|
||||
|
@ -238,14 +243,12 @@ public class DefaultHttpClientConnectionOperator implements HttpClientConnection
|
|||
Closer.closeQuietly(socket);
|
||||
if (last) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("{}:{} connection to {} failed ({}); terminating operation",
|
||||
host.getHostName(), host.getPort(), remoteAddress, ex.getClass());
|
||||
LOG.debug("{} connection to {} failed ({}); terminating operation", endpointHost, remoteAddress, ex.getClass());
|
||||
}
|
||||
throw ConnectExceptionSupport.enhance(ex, host, remoteAddresses);
|
||||
throw ConnectExceptionSupport.enhance(ex, endpointHost, remoteAddresses);
|
||||
} else {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("{}:{} connection to {} failed ({}); retrying connection to the next address",
|
||||
host.getHostName(), host.getPort(), remoteAddress, ex.getClass());
|
||||
LOG.debug("{} connection to {} failed ({}); retrying connection to the next address", endpointHost, remoteAddress, ex.getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -257,24 +260,28 @@ public class DefaultHttpClientConnectionOperator implements HttpClientConnection
|
|||
final ManagedHttpClientConnection conn,
|
||||
final HttpHost host,
|
||||
final HttpContext context) throws IOException {
|
||||
upgrade(conn, host, null, context);
|
||||
upgrade(conn, host, null, null, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void upgrade(
|
||||
final ManagedHttpClientConnection conn,
|
||||
final HttpHost host,
|
||||
final HttpHost endpointHost,
|
||||
final NamedEndpoint endpointName,
|
||||
final Object attachment,
|
||||
final HttpContext context) throws IOException {
|
||||
final Socket socket = conn.getSocket();
|
||||
if (socket == null) {
|
||||
throw new ConnectionClosedException("Connection is closed");
|
||||
}
|
||||
final String newProtocol = URIScheme.HTTP.same(host.getSchemeName()) ? URIScheme.HTTPS.id : host.getSchemeName();
|
||||
final String newProtocol = URIScheme.HTTP.same(endpointHost.getSchemeName()) ? URIScheme.HTTPS.id : endpointHost.getSchemeName();
|
||||
final TlsSocketStrategy tlsSocketStrategy = tlsSocketStrategyLookup != null ? tlsSocketStrategyLookup.lookup(newProtocol) : null;
|
||||
if (tlsSocketStrategy != null) {
|
||||
final int port = this.schemePortResolver.resolve(newProtocol, host);
|
||||
final SSLSocket upgradedSocket = tlsSocketStrategy.upgrade(socket, host.getHostName(), port, attachment, context);
|
||||
final NamedEndpoint tlsName = endpointName != null ? endpointName : endpointHost;
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("{} upgrading to TLS {}:{}", ConnPoolSupport.getId(conn), tlsName.getHostName(), tlsName.getPort());
|
||||
}
|
||||
final SSLSocket upgradedSocket = tlsSocketStrategy.upgrade(socket, tlsName.getHostName(), tlsName.getPort(), attachment, context);
|
||||
conn.bind(upgradedSocket);
|
||||
} else {
|
||||
throw new UnsupportedSchemeException(newProtocol + " protocol is not supported");
|
||||
|
|
|
@ -474,22 +474,22 @@ public class PoolingHttpClientConnectionManager
|
|||
poolEntry.assignConnection(connFactory.createConnection(null));
|
||||
}
|
||||
final HttpRoute route = poolEntry.getRoute();
|
||||
final HttpHost host = route.getProxyHost() != null ? route.getProxyHost() : route.getTargetHost();
|
||||
final HttpHost firstHop = route.getProxyHost() != null ? route.getProxyHost() : route.getTargetHost();
|
||||
final SocketConfig socketConfig = resolveSocketConfig(route);
|
||||
final ConnectionConfig connectionConfig = resolveConnectionConfig(route);
|
||||
final TlsConfig tlsConfig = resolveTlsConfig(host);
|
||||
final Timeout connectTimeout = timeout != null ? Timeout.of(timeout.getDuration(), timeout.getTimeUnit()) : connectionConfig.getConnectTimeout();
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("{} connecting endpoint to {} ({})", ConnPoolSupport.getId(endpoint), host, connectTimeout);
|
||||
LOG.debug("{} connecting endpoint to {} ({})", ConnPoolSupport.getId(endpoint), firstHop, connectTimeout);
|
||||
}
|
||||
final ManagedHttpClientConnection conn = poolEntry.getConnection();
|
||||
this.connectionOperator.connect(
|
||||
conn,
|
||||
host,
|
||||
firstHop,
|
||||
route.getTargetName(),
|
||||
route.getLocalSocketAddress(),
|
||||
connectTimeout,
|
||||
socketConfig,
|
||||
tlsConfig,
|
||||
route.isTunnelled() ? null : resolveTlsConfig(route.getTargetHost()),
|
||||
context);
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("{} connected {}", ConnPoolSupport.getId(endpoint), ConnPoolSupport.getId(conn));
|
||||
|
@ -505,9 +505,15 @@ public class PoolingHttpClientConnectionManager
|
|||
Args.notNull(endpoint, "Managed endpoint");
|
||||
final InternalConnectionEndpoint internalEndpoint = cast(endpoint);
|
||||
final PoolEntry<HttpRoute, ManagedHttpClientConnection> poolEntry = internalEndpoint.getValidatedPoolEntry();
|
||||
final HttpHost target = poolEntry.getRoute().getTargetHost();
|
||||
final HttpRoute route = poolEntry.getRoute();
|
||||
final HttpHost target = route.getTargetHost();
|
||||
final TlsConfig tlsConfig = resolveTlsConfig(target);
|
||||
this.connectionOperator.upgrade(poolEntry.getConnection(), target, tlsConfig, context);
|
||||
this.connectionOperator.upgrade(
|
||||
poolEntry.getConnection(),
|
||||
target,
|
||||
route.getTargetName(),
|
||||
tlsConfig,
|
||||
context);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.apache.hc.client5.http.DnsResolver;
|
|||
import org.apache.hc.client5.http.SchemePortResolver;
|
||||
import org.apache.hc.client5.http.UnsupportedSchemeException;
|
||||
import org.apache.hc.client5.http.config.TlsConfig;
|
||||
import org.apache.hc.client5.http.impl.ConnPoolSupport;
|
||||
import org.apache.hc.client5.http.impl.DefaultSchemePortResolver;
|
||||
import org.apache.hc.client5.http.nio.AsyncClientConnectionOperator;
|
||||
import org.apache.hc.client5.http.nio.ManagedAsyncClientConnection;
|
||||
|
@ -49,14 +50,19 @@ import org.apache.hc.core5.http.URIScheme;
|
|||
import org.apache.hc.core5.http.config.Lookup;
|
||||
import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
|
||||
import org.apache.hc.core5.http.protocol.HttpContext;
|
||||
import org.apache.hc.core5.net.NamedEndpoint;
|
||||
import org.apache.hc.core5.reactor.ConnectionInitiator;
|
||||
import org.apache.hc.core5.reactor.IOSession;
|
||||
import org.apache.hc.core5.reactor.ssl.TransportSecurityLayer;
|
||||
import org.apache.hc.core5.util.Args;
|
||||
import org.apache.hc.core5.util.Timeout;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
final class DefaultAsyncClientConnectionOperator implements AsyncClientConnectionOperator {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DefaultAsyncClientConnectionOperator.class);
|
||||
|
||||
private final SchemePortResolver schemePortResolver;
|
||||
private final MultihomeIOSessionRequester sessionRequester;
|
||||
private final Lookup<TlsStrategy> tlsStrategyLookup;
|
||||
|
@ -78,25 +84,31 @@ final class DefaultAsyncClientConnectionOperator implements AsyncClientConnectio
|
|||
final Timeout connectTimeout,
|
||||
final Object attachment,
|
||||
final FutureCallback<ManagedAsyncClientConnection> callback) {
|
||||
return connect(connectionInitiator, host, localAddress, connectTimeout,
|
||||
return connect(connectionInitiator, host, null, localAddress, connectTimeout,
|
||||
attachment, null, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<ManagedAsyncClientConnection> connect(
|
||||
final ConnectionInitiator connectionInitiator,
|
||||
final HttpHost host,
|
||||
final HttpHost endpointHost,
|
||||
final NamedEndpoint endpointName,
|
||||
final SocketAddress localAddress,
|
||||
final Timeout connectTimeout,
|
||||
final Object attachment,
|
||||
final HttpContext context,
|
||||
final FutureCallback<ManagedAsyncClientConnection> callback) {
|
||||
Args.notNull(connectionInitiator, "Connection initiator");
|
||||
Args.notNull(host, "Host");
|
||||
Args.notNull(endpointHost, "Host");
|
||||
final ComplexFuture<ManagedAsyncClientConnection> future = new ComplexFuture<>(callback);
|
||||
final HttpHost remoteEndpoint = RoutingSupport.normalize(host, schemePortResolver);
|
||||
final InetAddress remoteAddress = host.getAddress();
|
||||
final HttpHost remoteEndpoint = RoutingSupport.normalize(endpointHost, schemePortResolver);
|
||||
final InetAddress remoteAddress = endpointHost.getAddress();
|
||||
final TlsConfig tlsConfig = attachment instanceof TlsConfig ? (TlsConfig) attachment : TlsConfig.DEFAULT;
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("{} connecting {}->{} ({})", endpointHost, localAddress, remoteAddress, connectTimeout);
|
||||
}
|
||||
|
||||
final Future<IOSession> sessionFuture = sessionRequester.connect(
|
||||
connectionInitiator,
|
||||
remoteEndpoint,
|
||||
|
@ -109,14 +121,22 @@ final class DefaultAsyncClientConnectionOperator implements AsyncClientConnectio
|
|||
@Override
|
||||
public void completed(final IOSession session) {
|
||||
final DefaultManagedAsyncClientConnection connection = new DefaultManagedAsyncClientConnection(session);
|
||||
final TlsStrategy tlsStrategy = tlsStrategyLookup != null ? tlsStrategyLookup.lookup(host.getSchemeName()) : null;
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("{} {} connected {}->{}", ConnPoolSupport.getId(connection), endpointHost,
|
||||
connection.getLocalAddress(), connection.getRemoteAddress());
|
||||
}
|
||||
final TlsStrategy tlsStrategy = tlsStrategyLookup != null ? tlsStrategyLookup.lookup(endpointHost.getSchemeName()) : null;
|
||||
if (tlsStrategy != null) {
|
||||
try {
|
||||
final Timeout socketTimeout = connection.getSocketTimeout();
|
||||
final Timeout handshakeTimeout = tlsConfig.getHandshakeTimeout();
|
||||
final NamedEndpoint tlsName = endpointName != null ? endpointName : endpointHost;
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("{} {} upgrading to TLS", ConnPoolSupport.getId(connection), tlsName);
|
||||
}
|
||||
tlsStrategy.upgrade(
|
||||
connection,
|
||||
host,
|
||||
tlsName,
|
||||
attachment,
|
||||
handshakeTimeout != null ? handshakeTimeout : connectTimeout,
|
||||
new FutureContribution<TransportSecurityLayer>(future) {
|
||||
|
@ -156,32 +176,27 @@ final class DefaultAsyncClientConnectionOperator implements AsyncClientConnectio
|
|||
final ManagedAsyncClientConnection connection,
|
||||
final HttpHost host,
|
||||
final Object attachment) {
|
||||
upgrade(connection, host, attachment, null, null);
|
||||
upgrade(connection, host, null, attachment, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void upgrade(
|
||||
final ManagedAsyncClientConnection connection,
|
||||
final HttpHost host,
|
||||
final Object attachment,
|
||||
final HttpContext context) {
|
||||
upgrade(connection, host, attachment, context, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void upgrade(
|
||||
final ManagedAsyncClientConnection connection,
|
||||
final HttpHost host,
|
||||
final HttpHost endpointHost,
|
||||
final NamedEndpoint endpointName,
|
||||
final Object attachment,
|
||||
final HttpContext context,
|
||||
final FutureCallback<ManagedAsyncClientConnection> callback) {
|
||||
final String newProtocol = URIScheme.HTTP.same(host.getSchemeName()) ? URIScheme.HTTPS.id : host.getSchemeName();
|
||||
final HttpHost remoteEndpoint = RoutingSupport.normalize(host, schemePortResolver);
|
||||
final String newProtocol = URIScheme.HTTP.same(endpointHost.getSchemeName()) ? URIScheme.HTTPS.id : endpointHost.getSchemeName();
|
||||
final TlsStrategy tlsStrategy = tlsStrategyLookup != null ? tlsStrategyLookup.lookup(newProtocol) : null;
|
||||
if (tlsStrategy != null) {
|
||||
final NamedEndpoint tlsName = endpointName != null ? endpointName : endpointHost;
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("{} {} upgrading to TLS", ConnPoolSupport.getId(connection), tlsName);
|
||||
}
|
||||
tlsStrategy.upgrade(
|
||||
connection,
|
||||
remoteEndpoint,
|
||||
tlsName,
|
||||
attachment,
|
||||
null,
|
||||
new CallbackContribution<TransportSecurityLayer>(callback) {
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
|
||||
package org.apache.hc.client5.http.impl.nio;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
@ -441,25 +440,20 @@ public class PoolingAsyncClientConnectionManager implements AsyncClientConnectio
|
|||
}
|
||||
final PoolEntry<HttpRoute, ManagedAsyncClientConnection> poolEntry = internalEndpoint.getPoolEntry();
|
||||
final HttpRoute route = poolEntry.getRoute();
|
||||
final HttpHost host;
|
||||
if (route.getProxyHost() != null) {
|
||||
host = route.getProxyHost();
|
||||
} else {
|
||||
host = route.getTargetHost();
|
||||
}
|
||||
final InetSocketAddress localAddress = route.getLocalSocketAddress();
|
||||
final HttpHost firstHop = route.getProxyHost() != null ? route.getProxyHost(): route.getTargetHost();
|
||||
final ConnectionConfig connectionConfig = resolveConnectionConfig(route);
|
||||
final Timeout connectTimeout = timeout != null ? timeout : connectionConfig.getConnectTimeout();
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("{} connecting endpoint to {} ({})", ConnPoolSupport.getId(endpoint), host, connectTimeout);
|
||||
LOG.debug("{} connecting endpoint to {} ({})", ConnPoolSupport.getId(endpoint), firstHop, connectTimeout);
|
||||
}
|
||||
final Future<ManagedAsyncClientConnection> connectFuture = connectionOperator.connect(
|
||||
connectionInitiator,
|
||||
host,
|
||||
localAddress,
|
||||
firstHop,
|
||||
route.getTargetName(),
|
||||
route.getLocalSocketAddress(),
|
||||
connectTimeout,
|
||||
route.isTunnelled() ? null : resolveTlsConfig(host),
|
||||
route.isTunnelled() ? null : resolveTlsConfig(route.getTargetHost()),
|
||||
context,
|
||||
new FutureCallback<ManagedAsyncClientConnection>() {
|
||||
|
||||
|
@ -508,6 +502,7 @@ public class PoolingAsyncClientConnectionManager implements AsyncClientConnectio
|
|||
connectionOperator.upgrade(
|
||||
poolEntry.getConnection(),
|
||||
target,
|
||||
route.getTargetName(),
|
||||
attachment != null ? attachment : resolveTlsConfig(target),
|
||||
context,
|
||||
new CallbackContribution<ManagedAsyncClientConnection>(callback) {
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.apache.hc.core5.annotation.ThreadingBehavior;
|
|||
import org.apache.hc.core5.http.HttpHost;
|
||||
import org.apache.hc.core5.http.io.SocketConfig;
|
||||
import org.apache.hc.core5.http.protocol.HttpContext;
|
||||
import org.apache.hc.core5.net.NamedEndpoint;
|
||||
import org.apache.hc.core5.util.TimeValue;
|
||||
import org.apache.hc.core5.util.Timeout;
|
||||
|
||||
|
@ -70,24 +71,27 @@ public interface HttpClientConnectionOperator {
|
|||
* Connect the given managed connection to the remote endpoint.
|
||||
*
|
||||
* @param conn the managed connection.
|
||||
* @param host the address of the opposite endpoint.
|
||||
* @param endpointHost the address of the remote endpoint.
|
||||
* @param endpointName the name of the remote endpoint, if different from the endpoint host name,
|
||||
* {@code null} otherwise. Usually taken from the request URU authority.
|
||||
* @param localAddress the address of the local endpoint.
|
||||
* @param connectTimeout the timeout of the connect operation.
|
||||
* @param socketConfig the socket configuration.
|
||||
* @param attachment connect request attachment.
|
||||
* @param context the execution context.
|
||||
*
|
||||
* @since 5.2
|
||||
* @since 5.4
|
||||
*/
|
||||
default void connect(
|
||||
ManagedHttpClientConnection conn,
|
||||
HttpHost host,
|
||||
HttpHost endpointHost,
|
||||
NamedEndpoint endpointName,
|
||||
InetSocketAddress localAddress,
|
||||
Timeout connectTimeout,
|
||||
SocketConfig socketConfig,
|
||||
Object attachment,
|
||||
HttpContext context) throws IOException {
|
||||
connect(conn, host, localAddress, connectTimeout, socketConfig, context);
|
||||
connect(conn, endpointHost, localAddress, connectTimeout, socketConfig, context);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -108,7 +112,9 @@ public interface HttpClientConnectionOperator {
|
|||
* by using the TLS security protocol.
|
||||
*
|
||||
* @param conn the managed connection.
|
||||
* @param host the address of the opposite endpoint with TLS security.
|
||||
* @param endpointHost the address of the remote endpoint.
|
||||
* @param endpointName the name of the remote endpoint, if different from the endpoint host name,
|
||||
* {@code null} otherwise. Usually taken from the request URU authority.
|
||||
* @param attachment connect request attachment.
|
||||
* @param context the execution context.
|
||||
*
|
||||
|
@ -116,10 +122,11 @@ public interface HttpClientConnectionOperator {
|
|||
*/
|
||||
default void upgrade(
|
||||
ManagedHttpClientConnection conn,
|
||||
HttpHost host,
|
||||
HttpHost endpointHost,
|
||||
NamedEndpoint endpointName,
|
||||
Object attachment,
|
||||
HttpContext context) throws IOException {
|
||||
upgrade(conn, host, context);
|
||||
upgrade(conn, endpointHost, context);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.apache.hc.core5.annotation.ThreadingBehavior;
|
|||
import org.apache.hc.core5.concurrent.FutureCallback;
|
||||
import org.apache.hc.core5.http.HttpHost;
|
||||
import org.apache.hc.core5.http.protocol.HttpContext;
|
||||
import org.apache.hc.core5.net.NamedEndpoint;
|
||||
import org.apache.hc.core5.reactor.ConnectionInitiator;
|
||||
import org.apache.hc.core5.util.Timeout;
|
||||
|
||||
|
@ -73,24 +74,27 @@ public interface AsyncClientConnectionOperator {
|
|||
* the provided {@link ConnectionInitiator}.
|
||||
*
|
||||
* @param connectionInitiator the connection initiator.
|
||||
* @param host the address of the opposite endpoint.
|
||||
* @param endpointHost the address of the remote endpoint.
|
||||
* @param endpointName the name of the remote endpoint, if different from the endpoint host name,
|
||||
* {@code null} otherwise. Usually taken from the request URU authority.
|
||||
* @param localAddress the address of the local endpoint.
|
||||
* @param connectTimeout the timeout of the connect operation.
|
||||
* @param attachment the attachment, which can be any object representing custom parameter
|
||||
* of the operation.
|
||||
* @param context the execution context.
|
||||
* @param callback the future result callback.
|
||||
* @since 5.2
|
||||
* @since 5.4
|
||||
*/
|
||||
default Future<ManagedAsyncClientConnection> connect(
|
||||
ConnectionInitiator connectionInitiator,
|
||||
HttpHost host,
|
||||
HttpHost endpointHost,
|
||||
NamedEndpoint endpointName,
|
||||
SocketAddress localAddress,
|
||||
Timeout connectTimeout,
|
||||
Object attachment,
|
||||
HttpContext context,
|
||||
FutureCallback<ManagedAsyncClientConnection> callback) {
|
||||
return connect(connectionInitiator, host, localAddress, connectTimeout,
|
||||
return connect(connectionInitiator, endpointHost, localAddress, connectTimeout,
|
||||
attachment, callback);
|
||||
}
|
||||
|
||||
|
@ -110,38 +114,26 @@ public interface AsyncClientConnectionOperator {
|
|||
* by using the TLS security protocol.
|
||||
*
|
||||
* @param conn the managed connection.
|
||||
* @param host the address of the opposite endpoint with TLS security.
|
||||
* @param endpointHost the address of the remote endpoint.
|
||||
* @param endpointName the name of the remote endpoint, if different from the endpoint host name,
|
||||
* {@code null} otherwise. Usually taken from the request URU authority.
|
||||
* @param attachment the attachment, which can be any object representing custom parameter
|
||||
* of the operation.
|
||||
* @param context the execution context.
|
||||
* @param callback the future result callback.
|
||||
* @since 5.2
|
||||
* @since 5.4
|
||||
*/
|
||||
default void upgrade(
|
||||
ManagedAsyncClientConnection conn,
|
||||
HttpHost host,
|
||||
HttpHost endpointHost,
|
||||
NamedEndpoint endpointName,
|
||||
Object attachment,
|
||||
HttpContext context,
|
||||
FutureCallback<ManagedAsyncClientConnection> callback) {
|
||||
upgrade(conn, host, attachment, context);
|
||||
upgrade(conn, endpointHost, attachment);
|
||||
if (callback != null) {
|
||||
callback.completed(conn);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Upgrades transport security of the given managed connection
|
||||
* by using the TLS security protocol.
|
||||
*
|
||||
* @param conn the managed connection.
|
||||
* @param host the address of the opposite endpoint with TLS security.
|
||||
* @param attachment the attachment, which can be any object representing custom parameter
|
||||
* of the operation.
|
||||
* @param context the execution context.
|
||||
* @since 5.2
|
||||
*/
|
||||
default void upgrade(ManagedAsyncClientConnection conn, HttpHost host, Object attachment, HttpContext context) {
|
||||
upgrade(conn, host, attachment);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
package org.apache.hc.client5.http.examples;
|
||||
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import javax.net.ssl.SSLPeerUnverifiedException;
|
||||
import javax.net.ssl.SSLSession;
|
||||
|
||||
import org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
|
||||
import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
|
||||
import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder;
|
||||
import org.apache.hc.client5.http.async.methods.SimpleRequestProducer;
|
||||
import org.apache.hc.client5.http.async.methods.SimpleResponseConsumer;
|
||||
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
|
||||
import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
|
||||
import org.apache.hc.client5.http.protocol.HttpClientContext;
|
||||
import org.apache.hc.core5.concurrent.FutureCallback;
|
||||
import org.apache.hc.core5.http.HttpHost;
|
||||
import org.apache.hc.core5.http.message.StatusLine;
|
||||
import org.apache.hc.core5.io.CloseMode;
|
||||
|
||||
/**
|
||||
* This example demonstrates how to use SNI to send requests to a virtual HTTPS
|
||||
* endpoint using the async I/O.
|
||||
*/
|
||||
public class AsyncClientSNI {
|
||||
|
||||
public static void main(final String[] args) throws Exception {
|
||||
try (final CloseableHttpAsyncClient client = HttpAsyncClients.createSystem()) {
|
||||
|
||||
client.start();
|
||||
|
||||
final HttpHost target = new HttpHost("https", "www.google.com");
|
||||
final SimpleHttpRequest request = SimpleRequestBuilder.get()
|
||||
.setUri("https://www.google.ch/")
|
||||
.build();
|
||||
|
||||
final HttpClientContext clientContext = HttpClientContext.create();
|
||||
|
||||
System.out.println("Executing request " + request);
|
||||
final Future<SimpleHttpResponse> future = client.execute(
|
||||
target,
|
||||
SimpleRequestProducer.create(request),
|
||||
SimpleResponseConsumer.create(),
|
||||
null,
|
||||
clientContext,
|
||||
new FutureCallback<SimpleHttpResponse>() {
|
||||
|
||||
@Override
|
||||
public void completed(final SimpleHttpResponse response) {
|
||||
System.out.println(request + "->" + new StatusLine(response));
|
||||
final SSLSession sslSession = clientContext.getSSLSession();
|
||||
if (sslSession != null) {
|
||||
try {
|
||||
System.out.println("Peer: " + sslSession.getPeerPrincipal());
|
||||
System.out.println("TLS protocol: " + sslSession.getProtocol());
|
||||
System.out.println("TLS cipher suite: " + sslSession.getCipherSuite());
|
||||
} catch (final SSLPeerUnverifiedException ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(final Exception ex) {
|
||||
System.out.println(request + "->" + ex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelled() {
|
||||
System.out.println(request + " cancelled");
|
||||
}
|
||||
|
||||
});
|
||||
future.get();
|
||||
|
||||
System.out.println("Shutting down");
|
||||
client.close(CloseMode.GRACEFUL);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
package org.apache.hc.client5.http.examples;
|
||||
|
||||
import javax.net.ssl.SSLPeerUnverifiedException;
|
||||
import javax.net.ssl.SSLSession;
|
||||
|
||||
import org.apache.hc.client5.http.classic.methods.HttpGet;
|
||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
||||
import org.apache.hc.client5.http.impl.classic.HttpClients;
|
||||
import org.apache.hc.client5.http.protocol.HttpClientContext;
|
||||
import org.apache.hc.core5.http.HttpHost;
|
||||
import org.apache.hc.core5.http.io.entity.EntityUtils;
|
||||
import org.apache.hc.core5.http.message.StatusLine;
|
||||
|
||||
/**
|
||||
* This example demonstrates how to use SNI to send requests to a virtual HTTPS
|
||||
* endpoint using the classic I/O.
|
||||
*/
|
||||
public class ClientSNI {
|
||||
|
||||
public final static void main(final String[] args) throws Exception {
|
||||
try (CloseableHttpClient httpclient = HttpClients.createSystem()) {
|
||||
|
||||
final HttpHost target = new HttpHost("https", "www.google.com");
|
||||
final HttpGet httpget = new HttpGet("https://www.google.ch/");
|
||||
|
||||
System.out.println("Executing request " + httpget.getMethod() + " " + httpget.getUri());
|
||||
|
||||
final HttpClientContext clientContext = HttpClientContext.create();
|
||||
httpclient.execute(target, httpget, clientContext, response -> {
|
||||
System.out.println("----------------------------------------");
|
||||
System.out.println(httpget + "->" + new StatusLine(response));
|
||||
EntityUtils.consume(response.getEntity());
|
||||
final SSLSession sslSession = clientContext.getSSLSession();
|
||||
if (sslSession != null) {
|
||||
try {
|
||||
System.out.println("Peer: " + sslSession.getPeerPrincipal());
|
||||
System.out.println("TLS protocol: " + sslSession.getProtocol());
|
||||
System.out.println("TLS cipher suite: " + sslSession.getCipherSuite());
|
||||
} catch (final SSLPeerUnverifiedException ignore) {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -402,7 +402,7 @@ public class TestBasicHttpClientConnectionManager {
|
|||
Mockito.verify(schemePortResolver, Mockito.times(1)).resolve(target.getSchemeName(), target);
|
||||
Mockito.verify(detachedSocketFactory, Mockito.times(1)).create(null);
|
||||
Mockito.verify(socket, Mockito.times(1)).connect(new InetSocketAddress(remote, 8443), 234);
|
||||
Mockito.verify(tlsSocketStrategy).upgrade(socket, "somehost", 8443, tlsConfig, context);
|
||||
Mockito.verify(tlsSocketStrategy).upgrade(socket, "somehost", 443, tlsConfig, context);
|
||||
|
||||
mgr.connect(endpoint1, TimeValue.ofMilliseconds(123), context);
|
||||
|
||||
|
@ -410,7 +410,7 @@ public class TestBasicHttpClientConnectionManager {
|
|||
Mockito.verify(schemePortResolver, Mockito.times(2)).resolve(target.getSchemeName(), target);
|
||||
Mockito.verify(detachedSocketFactory, Mockito.times(2)).create(null);
|
||||
Mockito.verify(socket, Mockito.times(1)).connect(new InetSocketAddress(remote, 8443), 123);
|
||||
Mockito.verify(tlsSocketStrategy, Mockito.times(2)).upgrade(socket, "somehost", 8443, tlsConfig, context);
|
||||
Mockito.verify(tlsSocketStrategy, Mockito.times(2)).upgrade(socket, "somehost", 443, tlsConfig, context);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -458,9 +458,8 @@ public class TestBasicHttpClientConnectionManager {
|
|||
|
||||
mgr.upgrade(endpoint1, context);
|
||||
|
||||
Mockito.verify(schemePortResolver, Mockito.times(1)).resolve(target.getSchemeName(), target);
|
||||
Mockito.verify(tlsSocketStrategy, Mockito.times(1)).upgrade(
|
||||
socket, "somehost", 8443, tlsConfig, context);
|
||||
socket, "somehost", 443, tlsConfig, context);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ public class TestHttpClientConnectionOperator {
|
|||
.setSoLinger(50, TimeUnit.MILLISECONDS)
|
||||
.build();
|
||||
final InetSocketAddress localAddress = new InetSocketAddress(local, 0);
|
||||
connectionOperator.connect(conn, host, localAddress, Timeout.ofMilliseconds(123), socketConfig, null, context);
|
||||
connectionOperator.connect(conn, host, null, localAddress, Timeout.ofMilliseconds(123), socketConfig, null, context);
|
||||
|
||||
Mockito.verify(socket).setKeepAlive(true);
|
||||
Mockito.verify(socket).setReuseAddress(true);
|
||||
|
@ -137,17 +137,17 @@ public class TestHttpClientConnectionOperator {
|
|||
Mockito.when(tlsSocketStrategy.upgrade(
|
||||
Mockito.same(socket),
|
||||
Mockito.eq("somehost"),
|
||||
Mockito.eq(443),
|
||||
Mockito.anyInt(),
|
||||
Mockito.any(),
|
||||
Mockito.any())).thenReturn(upgradedSocket);
|
||||
|
||||
final InetSocketAddress localAddress = new InetSocketAddress(local, 0);
|
||||
connectionOperator.connect(conn, host, localAddress,
|
||||
connectionOperator.connect(conn, host, null, localAddress,
|
||||
Timeout.ofMilliseconds(123), SocketConfig.DEFAULT, tlsConfig, context);
|
||||
|
||||
Mockito.verify(socket).connect(new InetSocketAddress(ip1, 443), 123);
|
||||
Mockito.verify(conn, Mockito.times(2)).bind(socket);
|
||||
Mockito.verify(tlsSocketStrategy).upgrade(socket, "somehost", 443, tlsConfig, context);
|
||||
Mockito.verify(tlsSocketStrategy).upgrade(socket, "somehost", -1, tlsConfig, context);
|
||||
Mockito.verify(conn, Mockito.times(1)).bind(upgradedSocket);
|
||||
}
|
||||
|
||||
|
@ -203,7 +203,7 @@ public class TestHttpClientConnectionOperator {
|
|||
final InetSocketAddress localAddress = new InetSocketAddress(local, 0);
|
||||
final TlsConfig tlsConfig = TlsConfig.custom()
|
||||
.build();
|
||||
connectionOperator.connect(conn, host, localAddress,
|
||||
connectionOperator.connect(conn, host, null, localAddress,
|
||||
Timeout.ofMilliseconds(123), SocketConfig.DEFAULT, tlsConfig, context);
|
||||
|
||||
Mockito.verify(socket, Mockito.times(2)).bind(localAddress);
|
||||
|
@ -225,7 +225,7 @@ public class TestHttpClientConnectionOperator {
|
|||
final InetSocketAddress localAddress = new InetSocketAddress(local, 0);
|
||||
final TlsConfig tlsConfig = TlsConfig.custom()
|
||||
.build();
|
||||
connectionOperator.connect(conn, host, localAddress,
|
||||
connectionOperator.connect(conn, host, null, localAddress,
|
||||
Timeout.ofMilliseconds(123), SocketConfig.DEFAULT, tlsConfig, context);
|
||||
|
||||
Mockito.verify(socket).bind(localAddress);
|
||||
|
@ -242,17 +242,16 @@ public class TestHttpClientConnectionOperator {
|
|||
Mockito.when(conn.isOpen()).thenReturn(true);
|
||||
Mockito.when(conn.getSocket()).thenReturn(socket);
|
||||
Mockito.when(tlsSocketStrategyLookup.lookup("https")).thenReturn(tlsSocketStrategy);
|
||||
Mockito.when(schemePortResolver.resolve(host.getSchemeName(), host)).thenReturn(443);
|
||||
|
||||
final SSLSocket upgradedSocket = Mockito.mock(SSLSocket.class);
|
||||
Mockito.when(tlsSocketStrategy.upgrade(
|
||||
Mockito.any(),
|
||||
Mockito.eq("somehost"),
|
||||
Mockito.eq(443),
|
||||
Mockito.anyInt(),
|
||||
Mockito.eq(Timeout.ofMilliseconds(345)),
|
||||
Mockito.any())).thenReturn(upgradedSocket);
|
||||
|
||||
connectionOperator.upgrade(conn, host, Timeout.ofMilliseconds(345), context);
|
||||
connectionOperator.upgrade(conn, host, null, Timeout.ofMilliseconds(345), context);
|
||||
|
||||
Mockito.verify(conn).bind(upgradedSocket);
|
||||
}
|
||||
|
|
|
@ -270,7 +270,7 @@ public class TestPoolingHttpClientConnectionManager {
|
|||
Mockito.when(tlsSocketStrategy.upgrade(
|
||||
Mockito.same(socket),
|
||||
Mockito.eq("somehost"),
|
||||
Mockito.eq(8443),
|
||||
Mockito.anyInt(),
|
||||
Mockito.any(),
|
||||
Mockito.any())).thenReturn(upgradedSocket);
|
||||
|
||||
|
@ -280,7 +280,7 @@ public class TestPoolingHttpClientConnectionManager {
|
|||
Mockito.verify(schemePortResolver, Mockito.times(1)).resolve(target.getSchemeName(), target);
|
||||
Mockito.verify(detachedSocketFactory, Mockito.times(1)).create(null);
|
||||
Mockito.verify(socket, Mockito.times(1)).connect(new InetSocketAddress(remote, 8443), 234);
|
||||
Mockito.verify(tlsSocketStrategy).upgrade(socket, "somehost", 8443, tlsConfig, context);
|
||||
Mockito.verify(tlsSocketStrategy).upgrade(socket, "somehost", 443, tlsConfig, context);
|
||||
|
||||
mgr.connect(endpoint1, TimeValue.ofMilliseconds(123), context);
|
||||
|
||||
|
@ -288,7 +288,7 @@ public class TestPoolingHttpClientConnectionManager {
|
|||
Mockito.verify(schemePortResolver, Mockito.times(2)).resolve(target.getSchemeName(), target);
|
||||
Mockito.verify(detachedSocketFactory, Mockito.times(2)).create(null);
|
||||
Mockito.verify(socket, Mockito.times(1)).connect(new InetSocketAddress(remote, 8443), 123);
|
||||
Mockito.verify(tlsSocketStrategy, Mockito.times(2)).upgrade(socket, "somehost", 8443, tlsConfig, context);
|
||||
Mockito.verify(tlsSocketStrategy, Mockito.times(2)).upgrade(socket, "somehost", 443, tlsConfig, context);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -347,9 +347,8 @@ public class TestPoolingHttpClientConnectionManager {
|
|||
|
||||
mgr.upgrade(endpoint1, context);
|
||||
|
||||
Mockito.verify(schemePortResolver, Mockito.times(1)).resolve(target.getSchemeName(), target);
|
||||
Mockito.verify(tlsSocketStrategy, Mockito.times(1)).upgrade(
|
||||
socket, "somehost", 8443, tlsConfig, context);
|
||||
socket, "somehost", 443, tlsConfig, context);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue