From b10d43f2bb810913c421eb1ad6fe08b277692750 Mon Sep 17 00:00:00 2001
From: Oleg Kalnichevski
Date: Sun, 12 Sep 2021 14:54:32 +0200
Subject: [PATCH] HTTPCLIENT-2135: TLS configuration on a per-host basis
---
.../async/TestHttp1RequestReExecution.java | 7 +-
.../testing/async/TestHttpAsyncMinimal.java | 28 +--
.../async/TestHttpMinimalReactive.java | 28 +--
...chingHttpAsyncClientCompatibilityTest.java | 14 +-
.../HttpAsyncClientCompatibilityTest.java | 5 +-
.../sync/TestConnectionManagement.java | 14 +-
.../client5/http/config/ConnectionConfig.java | 7 +-
.../hc/client5/http/config/TlsConfig.java | 203 ++++++++++++++++++
.../impl/async/HttpAsyncClientBuilder.java | 15 +-
.../HttpAsyncClientEventHandlerFactory.java | 7 +-
.../http/impl/async/HttpAsyncClients.java | 65 +++++-
.../impl/async/InternalHttpAsyncClient.java | 10 +-
.../async/InternalHttpAsyncExecRuntime.java | 20 +-
.../impl/async/MinimalHttpAsyncClient.java | 12 +-
.../io/BasicHttpClientConnectionManager.java | 21 +-
.../DefaultHttpClientConnectionOperator.java | 34 ++-
.../PoolingHttpClientConnectionManager.java | 51 +++--
...ingHttpClientConnectionManagerBuilder.java | 25 +++
.../DefaultAsyncClientConnectionOperator.java | 9 +-
.../PoolingAsyncClientConnectionManager.java | 38 +++-
...ngAsyncClientConnectionManagerBuilder.java | 24 +++
.../http/io/HttpClientConnectionOperator.java | 44 ++++
.../nio/AsyncClientConnectionOperator.java | 1 -
.../http/socket/ConnectionSocketFactory.java | 32 +++
.../LayeredConnectionSocketFactory.java | 26 +++
.../http/ssl/AbstractClientTlsStrategy.java | 12 +-
.../http/ssl/SSLConnectionSocketFactory.java | 50 ++++-
.../AsyncClientFullDuplexExchange.java | 9 +-
.../AsyncClientH2FullDuplexExchange.java | 17 +-
.../examples/AsyncClientH2Multiplexing.java | 17 +-
.../examples/AsyncClientH2ServerPush.java | 23 +-
.../examples/AsyncClientHttp1Pipelining.java | 17 +-
.../http/examples/AsyncClientTlsAlpn.java | 2 -
.../ReactiveClientFullDuplexExchange.java | 9 +-
.../TestBasicHttpClientConnectionManager.java | 65 +++++-
.../io/TestHttpClientConnectionOperator.java | 39 +++-
...estPoolingHttpClientConnectionManager.java | 64 +++++-
37 files changed, 866 insertions(+), 198 deletions(-)
create mode 100644 httpclient5/src/main/java/org/apache/hc/client5/http/config/TlsConfig.java
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1RequestReExecution.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1RequestReExecution.java
index 4a7f00278..cb7a46588 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1RequestReExecution.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1RequestReExecution.java
@@ -34,6 +34,7 @@
import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder;
import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.config.TlsConfig;
import org.apache.hc.client5.http.impl.DefaultHttpRequestRetryStrategy;
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder;
@@ -102,12 +103,14 @@ protected void after() {
@Override
protected void before() throws Throwable {
+ connManager.setDefaultTlsConfig(TlsConfig.custom()
+ .setVersionPolicy(version.greaterEquals(HttpVersion.HTTP_2) ? HttpVersionPolicy.FORCE_HTTP_2 : HttpVersionPolicy.FORCE_HTTP_1)
+ .build());
clientBuilder = HttpAsyncClientBuilder.create()
.setDefaultRequestConfig(RequestConfig.custom()
.setConnectionRequestTimeout(TIMEOUT)
.build())
- .setConnectionManager(connManager)
- .setVersionPolicy(version.greaterEquals(HttpVersion.HTTP_2) ? HttpVersionPolicy.FORCE_HTTP_2 : HttpVersionPolicy.FORCE_HTTP_1);
+ .setConnectionManager(connManager);
}
};
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpAsyncMinimal.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpAsyncMinimal.java
index 5c5c073af..d4ccb3179 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpAsyncMinimal.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpAsyncMinimal.java
@@ -34,9 +34,9 @@
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
+import org.apache.hc.client5.http.config.TlsConfig;
import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
import org.apache.hc.client5.http.impl.async.MinimalHttpAsyncClient;
-import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager;
import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy;
@@ -85,19 +85,19 @@ public TestHttpAsyncMinimal(final HttpVersion version, final URIScheme scheme) {
@Override
protected MinimalHttpAsyncClient createClient() throws Exception {
- final PoolingAsyncClientConnectionManager connectionManager = PoolingAsyncClientConnectionManagerBuilder.create()
- .setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext()))
- .build();
- final IOReactorConfig ioReactorConfig = IOReactorConfig.custom()
- .setSoTimeout(TIMEOUT)
- .build();
- if (version.greaterEquals(HttpVersion.HTTP_2)) {
- return HttpAsyncClients.createMinimal(
- HttpVersionPolicy.FORCE_HTTP_2, H2Config.DEFAULT, Http1Config.DEFAULT, ioReactorConfig, connectionManager);
- } else {
- return HttpAsyncClients.createMinimal(
- HttpVersionPolicy.FORCE_HTTP_1, H2Config.DEFAULT, Http1Config.DEFAULT, ioReactorConfig, connectionManager);
- }
+ return HttpAsyncClients.createMinimal(
+ H2Config.DEFAULT,
+ Http1Config.DEFAULT,
+ IOReactorConfig.custom()
+ .setSoTimeout(TIMEOUT)
+ .build(),
+ PoolingAsyncClientConnectionManagerBuilder.create()
+ .setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext()))
+ .setDefaultTlsConfig(TlsConfig.custom()
+ .setVersionPolicy(version.greaterEquals(HttpVersion.HTTP_2)
+ ? HttpVersionPolicy.FORCE_HTTP_2 : HttpVersionPolicy.FORCE_HTTP_1)
+ .build())
+ .build());
}
@Override
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpMinimalReactive.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpMinimalReactive.java
index 5cbad4354..24749dcb5 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpMinimalReactive.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttpMinimalReactive.java
@@ -34,9 +34,9 @@
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
+import org.apache.hc.client5.http.config.TlsConfig;
import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
import org.apache.hc.client5.http.impl.async.MinimalHttpAsyncClient;
-import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager;
import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy;
@@ -85,19 +85,19 @@ public TestHttpMinimalReactive(final HttpVersion version, final URIScheme scheme
@Override
protected MinimalHttpAsyncClient createClient() throws Exception {
- final PoolingAsyncClientConnectionManager connectionManager = PoolingAsyncClientConnectionManagerBuilder.create()
- .setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext()))
- .build();
- final IOReactorConfig ioReactorConfig = IOReactorConfig.custom()
- .setSoTimeout(TIMEOUT)
- .build();
- if (version.greaterEquals(HttpVersion.HTTP_2)) {
- return HttpAsyncClients.createMinimal(
- HttpVersionPolicy.FORCE_HTTP_2, H2Config.DEFAULT, Http1Config.DEFAULT, ioReactorConfig, connectionManager);
- } else {
- return HttpAsyncClients.createMinimal(
- HttpVersionPolicy.FORCE_HTTP_1, H2Config.DEFAULT, Http1Config.DEFAULT, ioReactorConfig, connectionManager);
- }
+ return HttpAsyncClients.createMinimal(
+ H2Config.DEFAULT,
+ Http1Config.DEFAULT,
+ IOReactorConfig.custom()
+ .setSoTimeout(TIMEOUT)
+ .build(),
+ PoolingAsyncClientConnectionManagerBuilder.create()
+ .setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext()))
+ .setDefaultTlsConfig(TlsConfig.custom()
+ .setVersionPolicy(version.greaterEquals(HttpVersion.HTTP_2)
+ ? HttpVersionPolicy.FORCE_HTTP_2 : HttpVersionPolicy.FORCE_HTTP_1)
+ .build())
+ .build());
}
@Override
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/CachingHttpAsyncClientCompatibilityTest.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/CachingHttpAsyncClientCompatibilityTest.java
index 72a219da9..c4f309027 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/CachingHttpAsyncClientCompatibilityTest.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/CachingHttpAsyncClientCompatibilityTest.java
@@ -35,13 +35,12 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import javax.net.ssl.SSLContext;
-
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.cache.CacheResponseStatus;
import org.apache.hc.client5.http.cache.HttpCacheContext;
+import org.apache.hc.client5.http.config.TlsConfig;
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
import org.apache.hc.client5.http.impl.cache.CacheConfig;
import org.apache.hc.client5.http.impl.cache.CachingHttpAsyncClients;
@@ -88,17 +87,20 @@ HttpVersion.HTTP_2_0, new HttpHost("http", "localhost", 8080))
CachingHttpAsyncClientCompatibilityTest(final HttpVersion protocolVersion, final HttpHost target) throws Exception {
this.protocolVersion = protocolVersion;
this.target = target;
- final SSLContext sslContext = SSLContexts.custom()
- .loadTrustMaterial(getClass().getResource("/test-ca.keystore"), "nopassword".toCharArray()).build();
this.connManager = PoolingAsyncClientConnectionManagerBuilder.create()
- .setTlsStrategy(new DefaultClientTlsStrategy(sslContext))
+ .setTlsStrategy(new DefaultClientTlsStrategy(SSLContexts.custom()
+ .loadTrustMaterial(getClass().getResource("/test-ca.keystore"), "nopassword".toCharArray())
+ .build()))
+ .setDefaultTlsConfig(TlsConfig.custom()
+ .setVersionPolicy(this.protocolVersion == HttpVersion.HTTP_2 ?
+ HttpVersionPolicy.FORCE_HTTP_2 : HttpVersionPolicy.FORCE_HTTP_1)
+ .build())
.build();
this.client = CachingHttpAsyncClients.custom()
.setCacheConfig(CacheConfig.custom()
.setMaxObjectSize(20480)
.build())
.setResourceFactory(HeapResourceFactory.INSTANCE)
- .setVersionPolicy(this.protocolVersion == HttpVersion.HTTP_2 ? HttpVersionPolicy.FORCE_HTTP_2 : HttpVersionPolicy.FORCE_HTTP_1)
.setConnectionManager(this.connManager)
.build();
}
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/HttpAsyncClientCompatibilityTest.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/HttpAsyncClientCompatibilityTest.java
index c5903c5a4..ee3317be0 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/HttpAsyncClientCompatibilityTest.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/HttpAsyncClientCompatibilityTest.java
@@ -40,6 +40,7 @@
import org.apache.hc.client5.http.auth.Credentials;
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.config.TlsConfig;
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
@@ -139,9 +140,11 @@ public static void main(final String... args) throws Exception {
.loadTrustMaterial(getClass().getResource("/test-ca.keystore"), "nopassword".toCharArray()).build();
this.connManager = PoolingAsyncClientConnectionManagerBuilder.create()
.setTlsStrategy(new DefaultClientTlsStrategy(sslContext))
+ .setDefaultTlsConfig(TlsConfig.custom()
+ .setVersionPolicy(versionPolicy)
+ .build())
.build();
this.client = HttpAsyncClients.custom()
- .setVersionPolicy(this.versionPolicy)
.setConnectionManager(this.connManager)
.setProxy(this.proxy)
.setDefaultRequestConfig(requestConfig)
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestConnectionManagement.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestConnectionManagement.java
index 9b1f8fd11..824e4fa57 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestConnectionManagement.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestConnectionManagement.java
@@ -82,7 +82,7 @@ public void testReleaseConnection() throws Exception {
final LeaseRequest leaseRequest1 = this.connManager.lease("id1", route,null);
final ConnectionEndpoint endpoint1 = leaseRequest1.get(Timeout.ZERO_MILLISECONDS);
- this.connManager.connect(endpoint1, TimeValue.NEG_ONE_MILLISECOND, context);
+ this.connManager.connect(endpoint1, null, context);
final HttpProcessor httpProcessor = new DefaultHttpProcessor(
new RequestTargetHost(), new RequestContent(), new RequestConnControl());
@@ -104,7 +104,7 @@ public void testReleaseConnection() throws Exception {
final ConnectionEndpoint endpoint2 = leaseRequest3.get(Timeout.ZERO_MILLISECONDS);
Assert.assertFalse(endpoint2.isConnected());
- this.connManager.connect(endpoint2, TimeValue.NEG_ONE_MILLISECOND, context);
+ this.connManager.connect(endpoint2, null, context);
try (final ClassicHttpResponse response2 = endpoint2.execute("id2", request, exec, context)) {
Assert.assertEquals(HttpStatus.SC_OK, response2.getCode());
@@ -145,7 +145,7 @@ public void testReleaseConnectionWithTimeLimits() throws Exception {
final LeaseRequest leaseRequest1 = this.connManager.lease("id1", route,null);
final ConnectionEndpoint endpoint1 = leaseRequest1.get(Timeout.ZERO_MILLISECONDS);
- this.connManager.connect(endpoint1, TimeValue.NEG_ONE_MILLISECOND, context);
+ this.connManager.connect(endpoint1, null, context);
final HttpProcessor httpProcessor = new DefaultHttpProcessor(
new RequestTargetHost(), new RequestContent(), new RequestConnControl());
@@ -168,7 +168,7 @@ public void testReleaseConnectionWithTimeLimits() throws Exception {
final ConnectionEndpoint endpoint2 = leaseRequest3.get(Timeout.ZERO_MILLISECONDS);
Assert.assertFalse(endpoint2.isConnected());
- this.connManager.connect(endpoint2, TimeValue.NEG_ONE_MILLISECOND, context);
+ this.connManager.connect(endpoint2, null, context);
try (final ClassicHttpResponse response2 = endpoint2.execute("id2", request, exec, context)) {
Assert.assertEquals(HttpStatus.SC_OK, response2.getCode());
@@ -193,7 +193,7 @@ public void testReleaseConnectionWithTimeLimits() throws Exception {
Assert.assertFalse(endpoint4.isConnected());
// repeat the communication, no need to prepare the request again
- this.connManager.connect(endpoint4, TimeValue.NEG_ONE_MILLISECOND, context);
+ this.connManager.connect(endpoint4, null, context);
try (final ClassicHttpResponse response4 = endpoint4.execute("id4", request, exec, context)) {
Assert.assertEquals(HttpStatus.SC_OK, response4.getCode());
@@ -213,7 +213,7 @@ public void testCloseExpiredIdleConnections() throws Exception {
final LeaseRequest leaseRequest1 = this.connManager.lease("id1", route,null);
final ConnectionEndpoint endpoint1 = leaseRequest1.get(Timeout.ZERO_MILLISECONDS);
- this.connManager.connect(endpoint1, TimeValue.NEG_ONE_MILLISECOND, context);
+ this.connManager.connect(endpoint1, null, context);
Assert.assertEquals(1, this.connManager.getTotalStats().getLeased());
Assert.assertEquals(1, this.connManager.getStats(route).getLeased());
@@ -262,7 +262,7 @@ public void testCloseExpiredTTLConnections() throws Exception {
final LeaseRequest leaseRequest1 = this.connManager.lease("id1", route,null);
final ConnectionEndpoint endpoint1 = leaseRequest1.get(Timeout.ZERO_MILLISECONDS);
- this.connManager.connect(endpoint1, TimeValue.NEG_ONE_MILLISECOND, context);
+ this.connManager.connect(endpoint1, null, context);
Assert.assertEquals(1, this.connManager.getTotalStats().getLeased());
Assert.assertEquals(1, this.connManager.getStats(route).getLeased());
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/config/ConnectionConfig.java b/httpclient5/src/main/java/org/apache/hc/client5/http/config/ConnectionConfig.java
index 97ed58521..38ead6f53 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/config/ConnectionConfig.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/config/ConnectionConfig.java
@@ -126,7 +126,6 @@ public static class Builder {
this.connectTimeout = DEFAULT_CONNECT_TIMEOUT;
}
-
/**
* @see #setSocketTimeout(Timeout)
*/
@@ -138,7 +137,7 @@ public Builder setSocketTimeout(final int soTimeout, final TimeUnit timeUnit) {
/**
* Determines the default socket timeout value for I/O operations.
*
- * Default: {@code null}
+ * Default: {@code null} (undefined)
*
*
* @return the default socket timeout value for I/O operations.
@@ -150,8 +149,6 @@ public Builder setSocketTimeout(final Timeout soTimeout) {
/**
* Determines the timeout until a new connection is fully established.
- * This may also include transport security negotiation exchanges
- * such as {@code SSL} or {@code TLS} protocol negotiation).
*
* A timeout value of zero is interpreted as an infinite timeout.
*
@@ -177,7 +174,7 @@ public Builder setConnectTimeout(final long connectTimeout, final TimeUnit timeU
* be re-validated prior to being leased to the consumer. Negative values passed
* to this method disable connection validation.
*
- * Default: {@code null}
+ * Default: {@code null} (undefined)
*
*/
public Builder setValidateAfterInactivity(final TimeValue validateAfterInactivity) {
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/config/TlsConfig.java b/httpclient5/src/main/java/org/apache/hc/client5/http/config/TlsConfig.java
new file mode 100644
index 000000000..7a014e263
--- /dev/null
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/config/TlsConfig.java
@@ -0,0 +1,203 @@
+/*
+ * ====================================================================
+ * 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
+ * .
+ *
+ */
+
+package org.apache.hc.client5.http.config;
+
+import java.util.Arrays;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.http2.HttpVersionPolicy;
+import org.apache.hc.core5.util.Timeout;
+
+/**
+ * Immutable class encapsulating TLS protocol settings.
+ *
+ * @since 5.2
+ */
+@Contract(threading = ThreadingBehavior.IMMUTABLE)
+public class TlsConfig implements Cloneable {
+
+ public static final TlsConfig DEFAULT = new Builder().build();
+
+ private final Timeout handshakeTimeout;
+ private final String[] supportedProtocols;
+ private final String[] supportedCipherSuites;
+ private final HttpVersionPolicy httpVersionPolicy;
+
+ /**
+ * Intended for CDI compatibility
+ */
+ protected TlsConfig() {
+ this(null, null, null, null);
+ }
+
+ TlsConfig(
+ final Timeout handshakeTimeout,
+ final String[] supportedProtocols,
+ final String[] supportedCipherSuites,
+ final HttpVersionPolicy httpVersionPolicy) {
+ super();
+ this.handshakeTimeout = handshakeTimeout;
+ this.supportedProtocols = supportedProtocols;
+ this.supportedCipherSuites = supportedCipherSuites;
+ this.httpVersionPolicy = httpVersionPolicy;
+ }
+
+ /**
+ * @see Builder#setHandshakeTimeout(Timeout)
+ */
+ public Timeout getHandshakeTimeout() {
+ return handshakeTimeout;
+ }
+
+ /**
+ * @see Builder#setSupportedProtocols(String...)
+ */
+ public String[] getSupportedProtocols() {
+ return supportedProtocols != null ? supportedProtocols.clone() : null;
+ }
+
+ /**
+ * @see Builder#setSupportedCipherSuites(String...)
+ */
+ public String[] getSupportedCipherSuites() {
+ return supportedCipherSuites != null ? supportedCipherSuites.clone() : null;
+ }
+
+ /**
+ * @see Builder#setVersionPolicy(HttpVersionPolicy)
+ */
+ public HttpVersionPolicy getHttpVersionPolicy() {
+ return httpVersionPolicy;
+ }
+
+ @Override
+ protected TlsConfig clone() throws CloneNotSupportedException {
+ return (TlsConfig) super.clone();
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("[");
+ builder.append("handshakeTimeout=").append(handshakeTimeout);
+ builder.append(", supportedProtocols=").append(Arrays.asList(supportedProtocols));
+ builder.append(", supportedCipherSuites=").append(Arrays.asList(supportedCipherSuites));
+ builder.append(", httpVersionPolicy=").append(httpVersionPolicy);
+ builder.append("]");
+ return builder.toString();
+ }
+
+ public static TlsConfig.Builder custom() {
+ return new Builder();
+ }
+
+ public static TlsConfig.Builder copy(final TlsConfig config) {
+ return new Builder()
+ .setHandshakeTimeout(config.getHandshakeTimeout())
+ .setSupportedProtocols(config.getSupportedProtocols())
+ .setSupportedCipherSuites(config.getSupportedCipherSuites())
+ .setVersionPolicy(config.getHttpVersionPolicy());
+ }
+
+ public static class Builder {
+
+ private Timeout handshakeTimeout;
+ private String[] supportedProtocols;
+ private String[] supportedCipherSuites;
+ private HttpVersionPolicy versionPolicy;
+
+ /**
+ * Determines the timeout used by TLS session negotiation exchanges (session handshake).
+ *
+ * A timeout value of zero is interpreted as an infinite timeout.
+ *
+ *
+ * Default: {@code null} (undefined)
+ *
+ */
+ public Builder setHandshakeTimeout(final Timeout handshakeTimeout) {
+ this.handshakeTimeout = handshakeTimeout;
+ return this;
+ }
+
+ /**
+ * @see #setHandshakeTimeout(Timeout)
+ */
+ public Builder setHandshakeTimeout(final long handshakeTimeout, final TimeUnit timeUnit) {
+ this.handshakeTimeout = Timeout.of(handshakeTimeout, timeUnit);
+ return this;
+ }
+
+ /**
+ * Determines supported TLS protocols.
+ *
+ * Default: {@code null} (undefined)
+ *
+ */
+ public Builder setSupportedProtocols(final String... supportedProtocols) {
+ this.supportedProtocols = supportedProtocols;
+ return this;
+ }
+
+ /**
+ * Determines supported cipher suites.
+ *
+ * Default: {@code null} (undefined)
+ *
+ */
+ public Builder setSupportedCipherSuites(final String... supportedCipherSuites) {
+ this.supportedCipherSuites = supportedCipherSuites;
+ return this;
+ }
+
+ /**
+ * Determines the HTTP protocol policy. By default, connections are expected to use TLS ALPN
+ * extension to negotiate the application protocol to be used by both endpoints.
+ *
+ *
+ * Default: {@link HttpVersionPolicy#NEGOTIATE}
+ *
+ */
+ public Builder setVersionPolicy(final HttpVersionPolicy versionPolicy) {
+ this.versionPolicy = versionPolicy;
+ return this;
+ }
+
+ public TlsConfig build() {
+ return new TlsConfig(
+ handshakeTimeout,
+ supportedProtocols,
+ supportedCipherSuites,
+ versionPolicy != null ? versionPolicy : HttpVersionPolicy.NEGOTIATE);
+ }
+
+ }
+
+}
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientBuilder.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientBuilder.java
index 6127ce08e..394a228fc 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientBuilder.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientBuilder.java
@@ -47,6 +47,7 @@
import org.apache.hc.client5.http.auth.CredentialsProvider;
import org.apache.hc.client5.http.auth.StandardAuthScheme;
import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.config.TlsConfig;
import org.apache.hc.client5.http.cookie.BasicCookieStore;
import org.apache.hc.client5.http.cookie.CookieSpecFactory;
import org.apache.hc.client5.http.cookie.CookieStore;
@@ -196,7 +197,11 @@ private ExecInterceptorEntry(
}
- private HttpVersionPolicy versionPolicy;
+ /**
+ * @deprecated TLS should be configured by the connection manager
+ */
+ @Deprecated
+ private TlsConfig tlsConfig;
private AsyncClientConnectionManager connManager;
private boolean connManagerShared;
private IOReactorConfig ioReactorConfig;
@@ -254,9 +259,12 @@ protected HttpAsyncClientBuilder() {
/**
* Sets HTTP protocol version policy.
+ *
+ * @deprecated Use {@link TlsConfig} and connection nanager methods
*/
+ @Deprecated
public final HttpAsyncClientBuilder setVersionPolicy(final HttpVersionPolicy versionPolicy) {
- this.versionPolicy = versionPolicy;
+ this.tlsConfig = versionPolicy != null ? TlsConfig.custom().setVersionPolicy(versionPolicy).build() : null;
return this;
}
@@ -903,7 +911,6 @@ public CloseableHttpAsyncClient build() {
final IOEventHandlerFactory ioEventHandlerFactory = new HttpAsyncClientEventHandlerFactory(
new DefaultHttpProcessor(new H2RequestContent(), new H2RequestTargetHost(), new H2RequestConnControl()),
(request, context) -> pushConsumerRegistry.get(request),
- versionPolicy != null ? versionPolicy : HttpVersionPolicy.NEGOTIATE,
h2Config != null ? h2Config : H2Config.DEFAULT,
h1Config != null ? h1Config : Http1Config.DEFAULT,
charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT,
@@ -986,7 +993,7 @@ public CloseableHttpAsyncClient build() {
threadFactory != null ? threadFactory : new DefaultThreadFactory("httpclient-main", true),
connManagerCopy,
routePlannerCopy,
- versionPolicy != null ? versionPolicy : HttpVersionPolicy.NEGOTIATE,
+ tlsConfig,
cookieSpecRegistryCopy,
authSchemeRegistryCopy,
cookieStoreCopy,
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientEventHandlerFactory.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientEventHandlerFactory.java
index e543421a0..15e98de5b 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientEventHandlerFactory.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientEventHandlerFactory.java
@@ -74,7 +74,6 @@ class HttpAsyncClientEventHandlerFactory implements IOEventHandlerFactory {
private final HttpProcessor httpProcessor;
private final HandlerFactory exchangeHandlerFactory;
- private final HttpVersionPolicy versionPolicy;
private final H2Config h2Config;
private final Http1Config h1Config;
private final CharCodingConfig charCodingConfig;
@@ -85,14 +84,12 @@ class HttpAsyncClientEventHandlerFactory implements IOEventHandlerFactory {
HttpAsyncClientEventHandlerFactory(
final HttpProcessor httpProcessor,
final HandlerFactory exchangeHandlerFactory,
- final HttpVersionPolicy versionPolicy,
final H2Config h2Config,
final Http1Config h1Config,
final CharCodingConfig charCodingConfig,
final ConnectionReuseStrategy connectionReuseStrategy) {
this.httpProcessor = Args.notNull(httpProcessor, "HTTP processor");
this.exchangeHandlerFactory = exchangeHandlerFactory;
- this.versionPolicy = versionPolicy != null ? versionPolicy : HttpVersionPolicy.NEGOTIATE;
this.h2Config = h2Config != null ? h2Config : H2Config.DEFAULT;
this.h1Config = h1Config != null ? h1Config : Http1Config.DEFAULT;
this.charCodingConfig = charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT;
@@ -238,7 +235,7 @@ public void onOutputFlowControl(final HttpConnection connection, final int strea
ioSession,
http1StreamHandlerFactory,
http2StreamHandlerFactory,
- attachment instanceof HttpVersionPolicy ? (HttpVersionPolicy) attachment : versionPolicy);
+ attachment instanceof HttpVersionPolicy ? (HttpVersionPolicy) attachment : null);
}
final ClientHttp1StreamDuplexerFactory http1StreamHandlerFactory = new ClientHttp1StreamDuplexerFactory(
httpProcessor,
@@ -258,7 +255,7 @@ public void onOutputFlowControl(final HttpConnection connection, final int strea
ioSession,
http1StreamHandlerFactory,
http2StreamHandlerFactory,
- attachment instanceof HttpVersionPolicy ? (HttpVersionPolicy) attachment : versionPolicy);
+ attachment instanceof HttpVersionPolicy ? (HttpVersionPolicy) attachment : null);
}
}
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClients.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClients.java
index f7214eda5..ea8ec3a46 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClients.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClients.java
@@ -30,6 +30,7 @@
import org.apache.hc.client5.http.DnsResolver;
import org.apache.hc.client5.http.SchemePortResolver;
import org.apache.hc.client5.http.SystemDefaultDnsResolver;
+import org.apache.hc.client5.http.config.TlsConfig;
import org.apache.hc.client5.http.impl.DefaultClientConnectionReuseStrategy;
import org.apache.hc.client5.http.impl.DefaultSchemePortResolver;
import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
@@ -122,26 +123,29 @@ private static HttpProcessor createMinimalProtocolProcessor() {
private static MinimalHttpAsyncClient createMinimalHttpAsyncClientImpl(
final IOEventHandlerFactory eventHandlerFactory,
final AsyncPushConsumerRegistry pushConsumerRegistry,
- final HttpVersionPolicy versionPolicy,
final IOReactorConfig ioReactorConfig,
final AsyncClientConnectionManager connmgr,
- final SchemePortResolver schemePortResolver) {
+ final SchemePortResolver schemePortResolver,
+ final TlsConfig tlsConfig) {
return new MinimalHttpAsyncClient(
eventHandlerFactory,
pushConsumerRegistry,
- versionPolicy,
ioReactorConfig,
new DefaultThreadFactory("httpclient-main", true),
new DefaultThreadFactory("httpclient-dispatch", true),
connmgr,
- schemePortResolver);
+ schemePortResolver,
+ tlsConfig);
}
/**
* Creates {@link MinimalHttpAsyncClient} instance optimized for
* HTTP/1.1 and HTTP/2 message transport without advanced HTTP protocol
* functionality.
+ *
+ * @deprecated Use {@link #createMinimal(H2Config, Http1Config, IOReactorConfig, AsyncClientConnectionManager)}
*/
+ @Deprecated
public static MinimalHttpAsyncClient createMinimal(
final HttpVersionPolicy versionPolicy,
final H2Config h2Config,
@@ -153,16 +157,60 @@ public static MinimalHttpAsyncClient createMinimal(
new HttpAsyncClientEventHandlerFactory(
createMinimalProtocolProcessor(),
(request, context) -> pushConsumerRegistry.get(request),
- versionPolicy,
h2Config,
h1Config,
CharCodingConfig.DEFAULT,
DefaultClientConnectionReuseStrategy.INSTANCE),
pushConsumerRegistry,
- versionPolicy,
ioReactorConfig,
connmgr,
- DefaultSchemePortResolver.INSTANCE);
+ DefaultSchemePortResolver.INSTANCE,
+ versionPolicy != null ? TlsConfig.custom().setVersionPolicy(versionPolicy).build() : null);
+ }
+
+ /**
+ * Creates {@link MinimalHttpAsyncClient} instance optimized for
+ * HTTP/1.1 and HTTP/2 message transport without advanced HTTP protocol
+ * functionality.
+ *
+ * @since 5.2
+ */
+ public static MinimalHttpAsyncClient createMinimal(
+ final H2Config h2Config,
+ final Http1Config h1Config,
+ final IOReactorConfig ioReactorConfig,
+ final AsyncClientConnectionManager connmgr) {
+ final AsyncPushConsumerRegistry pushConsumerRegistry = new AsyncPushConsumerRegistry();
+ return createMinimalHttpAsyncClientImpl(
+ new HttpAsyncClientEventHandlerFactory(
+ createMinimalProtocolProcessor(),
+ (request, context) -> pushConsumerRegistry.get(request),
+ h2Config,
+ h1Config,
+ CharCodingConfig.DEFAULT,
+ DefaultClientConnectionReuseStrategy.INSTANCE),
+ pushConsumerRegistry,
+ ioReactorConfig,
+ connmgr,
+ DefaultSchemePortResolver.INSTANCE,
+ null);
+ }
+
+ /**
+ * Creates {@link MinimalHttpAsyncClient} instance optimized for
+ * HTTP/1.1 and HTTP/2 message transport without advanced HTTP protocol
+ * functionality.
+ *
+ * @deprecated Use {@link #createMinimal(H2Config, Http1Config, IOReactorConfig)}
+ */
+ @Deprecated
+ public static MinimalHttpAsyncClient createMinimal(
+ final HttpVersionPolicy versionPolicy,
+ final H2Config h2Config,
+ final Http1Config h1Config,
+ final IOReactorConfig ioReactorConfig) {
+ return createMinimal(versionPolicy, h2Config, h1Config, ioReactorConfig,
+ PoolingAsyncClientConnectionManagerBuilder.create().build());
}
/**
@@ -171,11 +219,10 @@ public static MinimalHttpAsyncClient createMinimal(
* functionality.
*/
public static MinimalHttpAsyncClient createMinimal(
- final HttpVersionPolicy versionPolicy,
final H2Config h2Config,
final Http1Config h1Config,
final IOReactorConfig ioReactorConfig) {
- return createMinimal(versionPolicy, h2Config, h1Config, ioReactorConfig,
+ return createMinimal(h2Config, h1Config, ioReactorConfig,
PoolingAsyncClientConnectionManagerBuilder.create().build());
}
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttpAsyncClient.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttpAsyncClient.java
index 2dc8a4218..746fe6224 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttpAsyncClient.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttpAsyncClient.java
@@ -35,6 +35,7 @@
import org.apache.hc.client5.http.auth.AuthSchemeFactory;
import org.apache.hc.client5.http.auth.CredentialsProvider;
import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.config.TlsConfig;
import org.apache.hc.client5.http.cookie.CookieSpecFactory;
import org.apache.hc.client5.http.cookie.CookieStore;
import org.apache.hc.client5.http.nio.AsyncClientConnectionManager;
@@ -48,7 +49,6 @@
import org.apache.hc.core5.http.config.Lookup;
import org.apache.hc.core5.http.nio.AsyncPushConsumer;
import org.apache.hc.core5.http.nio.HandlerFactory;
-import org.apache.hc.core5.http2.HttpVersionPolicy;
import org.apache.hc.core5.reactor.DefaultConnectingIOReactor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -71,7 +71,7 @@ public final class InternalHttpAsyncClient extends InternalAbstractHttpAsyncClie
private static final Logger LOG = LoggerFactory.getLogger(InternalHttpAsyncClient.class);
private final AsyncClientConnectionManager manager;
private final HttpRoutePlanner routePlanner;
- private final HttpVersionPolicy versionPolicy;
+ private final TlsConfig tlsConfig;
InternalHttpAsyncClient(
final DefaultConnectingIOReactor ioReactor,
@@ -80,7 +80,7 @@ public final class InternalHttpAsyncClient extends InternalAbstractHttpAsyncClie
final ThreadFactory threadFactory,
final AsyncClientConnectionManager manager,
final HttpRoutePlanner routePlanner,
- final HttpVersionPolicy versionPolicy,
+ final TlsConfig tlsConfig,
final Lookup cookieSpecRegistry,
final Lookup authSchemeRegistry,
final CookieStore cookieStore,
@@ -91,12 +91,12 @@ public final class InternalHttpAsyncClient extends InternalAbstractHttpAsyncClie
cookieSpecRegistry, authSchemeRegistry, cookieStore, credentialsProvider, defaultConfig, closeables);
this.manager = manager;
this.routePlanner = routePlanner;
- this.versionPolicy = versionPolicy;
+ this.tlsConfig = tlsConfig;
}
@Override
AsyncExecRuntime createAsyncExecRuntime(final HandlerFactory pushHandlerFactory) {
- return new InternalHttpAsyncExecRuntime(LOG, manager, getConnectionInitiator(), pushHandlerFactory, versionPolicy);
+ return new InternalHttpAsyncExecRuntime(LOG, manager, getConnectionInitiator(), pushHandlerFactory, tlsConfig);
}
@Override
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttpAsyncExecRuntime.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttpAsyncExecRuntime.java
index 390340340..ad7c56501 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttpAsyncExecRuntime.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttpAsyncExecRuntime.java
@@ -33,6 +33,7 @@
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.async.AsyncExecRuntime;
import org.apache.hc.client5.http.config.RequestConfig;
+import org.apache.hc.client5.http.config.TlsConfig;
import org.apache.hc.client5.http.impl.ConnPoolSupport;
import org.apache.hc.client5.http.impl.Operations;
import org.apache.hc.client5.http.nio.AsyncClientConnectionManager;
@@ -44,7 +45,6 @@
import org.apache.hc.core5.http.nio.AsyncClientExchangeHandler;
import org.apache.hc.core5.http.nio.AsyncPushConsumer;
import org.apache.hc.core5.http.nio.HandlerFactory;
-import org.apache.hc.core5.http2.HttpVersionPolicy;
import org.apache.hc.core5.io.CloseMode;
import org.apache.hc.core5.reactor.ConnectionInitiator;
import org.apache.hc.core5.util.TimeValue;
@@ -57,7 +57,11 @@ class InternalHttpAsyncExecRuntime implements AsyncExecRuntime {
private final AsyncClientConnectionManager manager;
private final ConnectionInitiator connectionInitiator;
private final HandlerFactory pushHandlerFactory;
- private final HttpVersionPolicy versionPolicy;
+ /**
+ * @deprecated TLS should be configured by the connection manager
+ */
+ @Deprecated
+ private final TlsConfig tlsConfig;
private final AtomicReference endpointRef;
private volatile boolean reusable;
private volatile Object state;
@@ -68,14 +72,14 @@ class InternalHttpAsyncExecRuntime implements AsyncExecRuntime {
final AsyncClientConnectionManager manager,
final ConnectionInitiator connectionInitiator,
final HandlerFactory pushHandlerFactory,
- final HttpVersionPolicy versionPolicy) {
+ final TlsConfig tlsConfig) {
super();
this.log = log;
this.manager = manager;
this.connectionInitiator = connectionInitiator;
this.pushHandlerFactory = pushHandlerFactory;
- this.versionPolicy = versionPolicy;
- this.endpointRef = new AtomicReference<>();
+ this.tlsConfig = tlsConfig;
+ this.endpointRef = new AtomicReference<>(null);
this.validDuration = TimeValue.NEG_ONE_MILLISECOND;
}
@@ -213,7 +217,7 @@ public Cancellable connectEndpoint(
endpoint,
connectionInitiator,
connectTimeout,
- versionPolicy,
+ tlsConfig,
context,
new CallbackContribution(callback) {
@@ -242,7 +246,7 @@ public void upgradeTls(final HttpClientContext context, final FutureCallback(callback) {
+ manager.upgrade(endpoint, tlsConfig, context, new CallbackContribution(callback) {
@Override
public void completed(final AsyncConnectionEndpoint endpoint) {
@@ -320,7 +324,7 @@ public void markConnectionNonReusable() {
@Override
public AsyncExecRuntime fork() {
- return new InternalHttpAsyncExecRuntime(log, manager, connectionInitiator, pushHandlerFactory, versionPolicy);
+ return new InternalHttpAsyncExecRuntime(log, manager, connectionInitiator, pushHandlerFactory, tlsConfig);
}
}
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/MinimalHttpAsyncClient.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/MinimalHttpAsyncClient.java
index 6a7bb4e94..5521eaf53 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/MinimalHttpAsyncClient.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/MinimalHttpAsyncClient.java
@@ -39,6 +39,7 @@
import org.apache.hc.client5.http.SchemePortResolver;
import org.apache.hc.client5.http.config.Configurable;
import org.apache.hc.client5.http.config.RequestConfig;
+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.impl.ExecSupport;
@@ -69,7 +70,6 @@
import org.apache.hc.core5.http.nio.RequestChannel;
import org.apache.hc.core5.http.nio.command.ShutdownCommand;
import org.apache.hc.core5.http.protocol.HttpContext;
-import org.apache.hc.core5.http2.HttpVersionPolicy;
import org.apache.hc.core5.io.CloseMode;
import org.apache.hc.core5.io.Closer;
import org.apache.hc.core5.reactor.Command;
@@ -101,17 +101,17 @@ public final class MinimalHttpAsyncClient extends AbstractMinimalHttpAsyncClient
private static final Logger LOG = LoggerFactory.getLogger(MinimalHttpAsyncClient.class);
private final AsyncClientConnectionManager manager;
private final SchemePortResolver schemePortResolver;
- private final HttpVersionPolicy versionPolicy;
+ private final TlsConfig tlsConfig;
MinimalHttpAsyncClient(
final IOEventHandlerFactory eventHandlerFactory,
final AsyncPushConsumerRegistry pushConsumerRegistry,
- final HttpVersionPolicy versionPolicy,
final IOReactorConfig reactorConfig,
final ThreadFactory threadFactory,
final ThreadFactory workerThreadFactory,
final AsyncClientConnectionManager manager,
- final SchemePortResolver schemePortResolver) {
+ final SchemePortResolver schemePortResolver,
+ final TlsConfig tlsConfig) {
super(new DefaultConnectingIOReactor(
eventHandlerFactory,
reactorConfig,
@@ -124,7 +124,7 @@ public final class MinimalHttpAsyncClient extends AbstractMinimalHttpAsyncClient
threadFactory);
this.manager = manager;
this.schemePortResolver = schemePortResolver != null ? schemePortResolver : DefaultSchemePortResolver.INSTANCE;
- this.versionPolicy = versionPolicy != null ? versionPolicy : HttpVersionPolicy.NEGOTIATE;
+ this.tlsConfig = tlsConfig;
}
private Future leaseEndpoint(
@@ -153,7 +153,7 @@ public void completed(final AsyncConnectionEndpoint connectionEndpoint) {
connectionEndpoint,
getConnectionInitiator(),
connectTimeout,
- versionPolicy,
+ tlsConfig,
clientContext,
new FutureCallback() {
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/BasicHttpClientConnectionManager.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/BasicHttpClientConnectionManager.java
index b9866c1a1..a67b3ad91 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/BasicHttpClientConnectionManager.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/BasicHttpClientConnectionManager.java
@@ -39,6 +39,7 @@
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.SchemePortResolver;
import org.apache.hc.client5.http.config.ConnectionConfig;
+import org.apache.hc.client5.http.config.TlsConfig;
import org.apache.hc.client5.http.impl.ConnPoolSupport;
import org.apache.hc.client5.http.impl.ConnectionShutdownException;
import org.apache.hc.client5.http.io.ConnectionEndpoint;
@@ -109,6 +110,7 @@ public class BasicHttpClientConnectionManager implements HttpClientConnectionMan
private boolean leased;
private SocketConfig socketConfig;
private ConnectionConfig connectionConfig;
+ private TlsConfig tlsConfig;
private final AtomicBoolean closed;
@@ -142,6 +144,8 @@ public BasicHttpClientConnectionManager(
this.id = String.format("ep-%010d", COUNT.getAndIncrement());
this.expiry = Long.MAX_VALUE;
this.socketConfig = SocketConfig.DEFAULT;
+ this.connectionConfig = ConnectionConfig.DEFAULT;
+ this.tlsConfig = TlsConfig.DEFAULT;
this.closed = new AtomicBoolean(false);
this.validateAfterInactivity = TimeValue.ofSeconds(2L);
}
@@ -203,6 +207,13 @@ public synchronized void setConnectionConfig(final ConnectionConfig connectionCo
this.connectionConfig = connectionConfig != null ? connectionConfig : ConnectionConfig.DEFAULT;
}
+ /**
+ * @since 5.2
+ */
+ public synchronized void setTlsConfig(final TlsConfig tlsConfig) {
+ this.tlsConfig = tlsConfig != null ? tlsConfig : TlsConfig.DEFAULT;
+ }
+
public LeaseRequest lease(final String id, final HttpRoute route, final Object state) {
return lease(id, route, Timeout.DISABLED, state);
}
@@ -358,8 +369,7 @@ public synchronized void connect(final ConnectionEndpoint endpoint, final TimeVa
} else {
host = route.getTargetHost();
}
- final ConnectionConfig config = connectionConfig != null ? connectionConfig : ConnectionConfig.DEFAULT;
- final TimeValue connectTimeout = timeout != null ? timeout : config.getConnectTimeout();
+ 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);
@@ -369,12 +379,13 @@ public synchronized void connect(final ConnectionEndpoint endpoint, final TimeVa
host,
route.getLocalSocketAddress(),
connectTimeout,
- this.socketConfig,
+ socketConfig,
+ tlsConfig,
context);
if (LOG.isDebugEnabled()) {
LOG.debug("{} connected {}", ConnPoolSupport.getId(endpoint), ConnPoolSupport.getId(conn));
}
- final Timeout socketTimeout = config.getSocketTimeout();
+ final Timeout socketTimeout = connectionConfig.getSocketTimeout();
if (socketTimeout != null) {
connection.setSocketTimeout(socketTimeout);
}
@@ -387,9 +398,11 @@ public synchronized void upgrade(
Args.notNull(endpoint, "Endpoint");
Args.notNull(route, "HTTP route");
final InternalConnectionEndpoint internalEndpoint = cast(endpoint);
+ final ConnectionConfig config = connectionConfig != null ? connectionConfig : ConnectionConfig.DEFAULT;
this.connectionOperator.upgrade(
internalEndpoint.getConnection(),
internalEndpoint.getRoute().getTargetHost(),
+ tlsConfig,
context);
}
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/DefaultHttpClientConnectionOperator.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/DefaultHttpClientConnectionOperator.java
index 926f58878..8f7eef802 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/DefaultHttpClientConnectionOperator.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/DefaultHttpClientConnectionOperator.java
@@ -54,6 +54,7 @@
import org.apache.hc.core5.http.protocol.HttpContext;
import org.apache.hc.core5.util.Args;
import org.apache.hc.core5.util.TimeValue;
+import org.apache.hc.core5.util.Timeout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -107,6 +108,19 @@ public void connect(
final TimeValue connectTimeout,
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);
+ }
+
+ @Override
+ public void connect(
+ final ManagedHttpClientConnection conn,
+ final HttpHost host,
+ 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(socketConfig, "Socket config");
@@ -131,13 +145,17 @@ public void connect(
}
}
+ final Timeout soTimeout = socketConfig.getSoTimeout();
+
final int port = this.schemePortResolver.resolve(host);
for (int i = 0; i < remoteAddresses.length; i++) {
final InetAddress address = remoteAddresses[i];
final boolean last = i == remoteAddresses.length - 1;
Socket sock = sf.createSocket(context);
- sock.setSoTimeout(socketConfig.getSoTimeout().toMillisecondsIntBound());
+ if (soTimeout != null) {
+ sock.setSoTimeout(soTimeout.toMillisecondsIntBound());
+ }
sock.setReuseAddress(socketConfig.isSoReuseAddress());
sock.setTcpNoDelay(socketConfig.isTcpNoDelay());
sock.setKeepAlive(socketConfig.isSoKeepAlive());
@@ -160,8 +178,9 @@ public void connect(
host.getHostName(), host.getPort(), localAddress, remoteAddress, connectTimeout);
}
try {
- sock = sf.connectSocket(connectTimeout, sock, host, remoteAddress, localAddress, context);
+ sock = sf.connectSocket(sock, host, remoteAddress, localAddress, connectTimeout, attachment, context);
conn.bind(sock);
+ conn.setSocketTimeout(soTimeout);
if (LOG.isDebugEnabled()) {
LOG.debug("{}:{} connected {}->{} as {}",
host.getHostName(), host.getPort(), localAddress, remoteAddress, ConnPoolSupport.getId(conn));
@@ -189,6 +208,15 @@ public void upgrade(
final ManagedHttpClientConnection conn,
final HttpHost host,
final HttpContext context) throws IOException {
+ upgrade(conn, host, null, context);
+ }
+
+ @Override
+ public void upgrade(
+ final ManagedHttpClientConnection conn,
+ final HttpHost host,
+ final Object attachment,
+ final HttpContext context) throws IOException {
final HttpClientContext clientContext = HttpClientContext.adapt(context);
final Lookup registry = getSocketFactoryRegistry(clientContext);
final ConnectionSocketFactory sf = registry.lookup(host.getSchemeName());
@@ -206,7 +234,7 @@ public void upgrade(
throw new ConnectionClosedException("Connection is closed");
}
final int port = this.schemePortResolver.resolve(host);
- sock = lsf.createLayeredSocket(sock, host.getHostName(), port, context);
+ sock = lsf.createLayeredSocket(sock, host.getHostName(), port, attachment, context);
conn.bind(sock);
}
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/PoolingHttpClientConnectionManager.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/PoolingHttpClientConnectionManager.java
index 22a29e980..8c415fc70 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/PoolingHttpClientConnectionManager.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/PoolingHttpClientConnectionManager.java
@@ -39,6 +39,7 @@
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.SchemePortResolver;
import org.apache.hc.client5.http.config.ConnectionConfig;
+import org.apache.hc.client5.http.config.TlsConfig;
import org.apache.hc.client5.http.impl.ConnPoolSupport;
import org.apache.hc.client5.http.impl.ConnectionShutdownException;
import org.apache.hc.client5.http.io.ConnectionEndpoint;
@@ -115,6 +116,7 @@ public class PoolingHttpClientConnectionManager
private volatile Resolver socketConfigResolver;
private volatile Resolver connectionConfigResolver;
+ private volatile Resolver tlsConfigResolver;
public PoolingHttpClientConnectionManager() {
this(RegistryBuilder.create()
@@ -241,16 +243,22 @@ private InternalConnectionEndpoint cast(final ConnectionEndpoint endpoint) {
throw new IllegalStateException("Unexpected endpoint class: " + endpoint.getClass());
}
+ private SocketConfig resolveSocketConfig(final HttpRoute route) {
+ final Resolver resolver = this.socketConfigResolver;
+ final SocketConfig socketConfig = resolver != null ? resolver.resolve(route) : null;
+ return socketConfig != null ? socketConfig : SocketConfig.DEFAULT;
+ }
+
private ConnectionConfig resolveConnectionConfig(final HttpRoute route) {
final Resolver resolver = this.connectionConfigResolver;
final ConnectionConfig connectionConfig = resolver != null ? resolver.resolve(route) : null;
return connectionConfig != null ? connectionConfig : ConnectionConfig.DEFAULT;
}
- private SocketConfig resolveSocketConfig(final HttpRoute route) {
- final Resolver resolver = this.socketConfigResolver;
- final SocketConfig socketConfig = resolver != null ? resolver.resolve(route) : null;
- return socketConfig != null ? socketConfig : SocketConfig.DEFAULT;
+ private TlsConfig resolveTlsConfig(final HttpHost host) {
+ final Resolver resolver = this.tlsConfigResolver;
+ final TlsConfig tlsConfig = resolver != null ? resolver.resolve(host) : null;
+ return tlsConfig != null ? tlsConfig : TlsConfig.DEFAULT;
}
private TimeValue resolveValidateAfterInactivity(final ConnectionConfig connectionConfig) {
@@ -401,15 +409,11 @@ public void connect(final ConnectionEndpoint endpoint, final TimeValue timeout,
poolEntry.assignConnection(connFactory.createConnection(null));
}
final HttpRoute route = poolEntry.getRoute();
- final HttpHost host;
- if (route.getProxyHost() != null) {
- host = route.getProxyHost();
- } else {
- host = route.getTargetHost();
- }
+ final HttpHost host = route.getProxyHost() != null ? route.getProxyHost() : route.getTargetHost();
final SocketConfig socketConfig = resolveSocketConfig(route);
final ConnectionConfig connectionConfig = resolveConnectionConfig(route);
- final TimeValue connectTimeout = timeout != null ? timeout : connectionConfig.getConnectTimeout();
+ 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);
}
@@ -418,8 +422,9 @@ public void connect(final ConnectionEndpoint endpoint, final TimeValue timeout,
conn,
host,
route.getLocalSocketAddress(),
- timeout,
+ connectTimeout,
socketConfig,
+ tlsConfig,
context);
if (LOG.isDebugEnabled()) {
LOG.debug("{} connected {}", ConnPoolSupport.getId(endpoint), ConnPoolSupport.getId(conn));
@@ -436,7 +441,9 @@ public void upgrade(final ConnectionEndpoint endpoint, final HttpContext context
final InternalConnectionEndpoint internalEndpoint = cast(endpoint);
final PoolEntry poolEntry = internalEndpoint.getValidatedPoolEntry();
final HttpRoute route = poolEntry.getRoute();
- this.connectionOperator.upgrade(poolEntry.getConnection(), route.getTargetHost(), context);
+ final HttpHost host = route.getProxyHost() != null ? route.getProxyHost() : route.getTargetHost();
+ final TlsConfig tlsConfig = resolveTlsConfig(host);
+ this.connectionOperator.upgrade(poolEntry.getConnection(), route.getTargetHost(), tlsConfig, context);
}
@Override
@@ -533,6 +540,24 @@ public void setConnectionConfigResolver(final Resolver config;
+ }
+
+ /**
+ * Sets {@link Resolver} of {@link TlsConfig} on a per host basis.
+ *
+ * @since 5.2
+ */
+ public void setTlsConfigResolver(final Resolver tlsConfigResolver) {
+ this.tlsConfigResolver = tlsConfigResolver;
+ }
+
/**
* @deprecated Use custom {@link #setConnectionConfigResolver(Resolver)}
*/
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/PoolingHttpClientConnectionManagerBuilder.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/PoolingHttpClientConnectionManagerBuilder.java
index e52f9acc7..c150e23c1 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/PoolingHttpClientConnectionManagerBuilder.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/PoolingHttpClientConnectionManagerBuilder.java
@@ -31,12 +31,14 @@
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.SchemePortResolver;
import org.apache.hc.client5.http.config.ConnectionConfig;
+import org.apache.hc.client5.http.config.TlsConfig;
import org.apache.hc.client5.http.io.ManagedHttpClientConnection;
import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
import org.apache.hc.client5.http.socket.LayeredConnectionSocketFactory;
import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory;
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
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.config.RegistryBuilder;
import org.apache.hc.core5.http.io.HttpConnectionFactory;
@@ -81,6 +83,7 @@ public class PoolingHttpClientConnectionManagerBuilder {
private PoolReusePolicy poolReusePolicy;
private Resolver socketConfigResolver;
private Resolver connectionConfigResolver;
+ private Resolver tlsConfigResolver;
private boolean systemProperties;
@@ -203,6 +206,27 @@ public final PoolingHttpClientConnectionManagerBuilder setConnectionConfigResolv
return this;
}
+ /**
+ * Assigns the same {@link TlsConfig} for all hosts.
+ *
+ * @since 5.2
+ */
+ public final PoolingHttpClientConnectionManagerBuilder setDefaultTlsConfig(final TlsConfig config) {
+ this.tlsConfigResolver = (host) -> config;
+ return this;
+ }
+
+ /**
+ * Assigns {@link Resolver} of {@link TlsConfig} on a per host basis.
+ *
+ * @since 5.2
+ */
+ public final PoolingHttpClientConnectionManagerBuilder setTlsConfigResolver(
+ final Resolver tlsConfigResolver) {
+ this.tlsConfigResolver = tlsConfigResolver;
+ return this;
+ }
+
/**
* Sets maximum time to live for persistent connections
*/
@@ -251,6 +275,7 @@ public PoolingHttpClientConnectionManager build() {
connectionFactory);
poolingmgr.setSocketConfigResolver(socketConfigResolver);
poolingmgr.setConnectionConfigResolver(connectionConfigResolver);
+ poolingmgr.setTlsConfigResolver(tlsConfigResolver);
if (maxConnTotal > 0) {
poolingmgr.setMaxTotal(maxConnTotal);
}
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/DefaultAsyncClientConnectionOperator.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/DefaultAsyncClientConnectionOperator.java
index a781e9bb9..130eb6bf0 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/DefaultAsyncClientConnectionOperator.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/DefaultAsyncClientConnectionOperator.java
@@ -34,6 +34,7 @@
import org.apache.hc.client5.http.DnsResolver;
import org.apache.hc.client5.http.SchemePortResolver;
+import org.apache.hc.client5.http.config.TlsConfig;
import org.apache.hc.client5.http.impl.DefaultSchemePortResolver;
import org.apache.hc.client5.http.nio.AsyncClientConnectionOperator;
import org.apache.hc.client5.http.nio.ManagedAsyncClientConnection;
@@ -81,13 +82,14 @@ public Future connect(
final HttpHost remoteEndpoint = RoutingSupport.normalize(host, schemePortResolver);
final InetAddress remoteAddress = host.getAddress();
final TlsStrategy tlsStrategy = tlsStrategyLookup != null ? tlsStrategyLookup.lookup(host.getSchemeName()) : null;
+ final TlsConfig tlsConfig = attachment instanceof TlsConfig ? (TlsConfig) attachment : TlsConfig.DEFAULT;
final Future sessionFuture = sessionRequester.connect(
connectionInitiator,
remoteEndpoint,
remoteAddress != null ? new InetSocketAddress(remoteAddress, remoteEndpoint.getPort()) : null,
localAddress,
connectTimeout,
- attachment,
+ tlsConfig.getHttpVersionPolicy(),
new FutureCallback() {
@Override
@@ -95,15 +97,18 @@ public void completed(final IOSession session) {
final DefaultManagedAsyncClientConnection connection = new DefaultManagedAsyncClientConnection(session);
if (tlsStrategy != null && URIScheme.HTTPS.same(host.getSchemeName())) {
try {
+ final Timeout socketTimeout = connection.getSocketTimeout();
+ final Timeout handshakeTimeout = tlsConfig.getHandshakeTimeout();
tlsStrategy.upgrade(
connection,
host,
attachment,
- null,
+ handshakeTimeout != null ? handshakeTimeout : connectTimeout,
new FutureContribution(future) {
@Override
public void completed(final TransportSecurityLayer transportSecurityLayer) {
+ connection.setSocketTimeout(socketTimeout);
future.completed(connection);
}
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManager.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManager.java
index 3617b592e..d5071544a 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManager.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManager.java
@@ -41,6 +41,7 @@
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.SchemePortResolver;
import org.apache.hc.client5.http.config.ConnectionConfig;
+import org.apache.hc.client5.http.config.TlsConfig;
import org.apache.hc.client5.http.impl.ConnPoolSupport;
import org.apache.hc.client5.http.impl.ConnectionShutdownException;
import org.apache.hc.client5.http.nio.AsyncClientConnectionManager;
@@ -123,6 +124,7 @@ public class PoolingAsyncClientConnectionManager implements AsyncClientConnectio
private final AtomicBoolean closed;
private volatile Resolver connectionConfigResolver;
+ private volatile Resolver tlsConfigResolver;
public PoolingAsyncClientConnectionManager() {
this(RegistryBuilder.create()
@@ -227,6 +229,15 @@ private ConnectionConfig resolveConnectionConfig(final HttpRoute route) {
return connectionConfig != null ? connectionConfig : ConnectionConfig.DEFAULT;
}
+ private TlsConfig resolveTlsConfig(final HttpHost host, final Object attachment) {
+ if (attachment instanceof TlsConfig) {
+ return (TlsConfig) attachment;
+ }
+ final Resolver resolver = this.tlsConfigResolver;
+ final TlsConfig tlsConfig = resolver != null ? resolver.resolve(host) : null;
+ return tlsConfig != null ? tlsConfig : TlsConfig.DEFAULT;
+ }
+
@Override
public Future lease(
final String id,
@@ -400,6 +411,7 @@ public Future connect(
}
final InetSocketAddress localAddress = route.getLocalSocketAddress();
final ConnectionConfig connectionConfig = resolveConnectionConfig(route);
+ final TlsConfig tlsConfig = resolveTlsConfig(host, attachment);
final Timeout connectTimeout = timeout != null ? timeout : connectionConfig.getConnectTimeout();
if (LOG.isDebugEnabled()) {
@@ -410,7 +422,9 @@ public Future connect(
host,
localAddress,
connectTimeout,
- route.isTunnelled() ? HttpVersionPolicy.FORCE_HTTP_1 : attachment,
+ route.isTunnelled() ? TlsConfig.copy(tlsConfig)
+ .setVersionPolicy(HttpVersionPolicy.FORCE_HTTP_1)
+ .build() : tlsConfig,
new FutureCallback() {
@Override
@@ -455,10 +469,12 @@ public void upgrade(
final InternalConnectionEndpoint internalEndpoint = cast(endpoint);
final PoolEntry poolEntry = internalEndpoint.getValidatedPoolEntry();
final HttpRoute route = poolEntry.getRoute();
+ final HttpHost host = route.getProxyHost() != null ? route.getProxyHost() : route.getTargetHost();
+ final TlsConfig tlsConfig = resolveTlsConfig(host, attachment);
connectionOperator.upgrade(
poolEntry.getConnection(),
route.getTargetHost(),
- attachment,
+ attachment != null ? attachment : tlsConfig,
new CallbackContribution(callback) {
@Override
@@ -566,6 +582,24 @@ public void setConnectionConfigResolver(final Resolver config;
+ }
+
+ /**
+ * Sets {@link Resolver} of {@link TlsConfig} on a per host basis.
+ *
+ * @since 5.2
+ */
+ public void setTlsConfigResolver(final Resolver tlsConfigResolver) {
+ this.tlsConfigResolver = tlsConfigResolver;
+ }
+
/**
* @deprecated Use custom {@link #setConnectionConfigResolver(Resolver)}
*/
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManagerBuilder.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManagerBuilder.java
index a8d44b0fa..122e0004e 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManagerBuilder.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/nio/PoolingAsyncClientConnectionManagerBuilder.java
@@ -31,9 +31,11 @@
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.SchemePortResolver;
import org.apache.hc.client5.http.config.ConnectionConfig;
+import org.apache.hc.client5.http.config.TlsConfig;
import org.apache.hc.client5.http.ssl.ConscryptClientTlsStrategy;
import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy;
import org.apache.hc.core5.function.Resolver;
+import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.config.RegistryBuilder;
import org.apache.hc.core5.http.io.SocketConfig;
import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
@@ -83,6 +85,7 @@ public class PoolingAsyncClientConnectionManagerBuilder {
private Resolver socketConfigResolver;
private Resolver connectionConfigResolver;
+ private Resolver tlsConfigResolver;
private TimeValue timeToLive;
public static PoolingAsyncClientConnectionManagerBuilder create() {
@@ -171,6 +174,26 @@ public final PoolingAsyncClientConnectionManagerBuilder setConnectionConfigResol
return this;
}
+ /**
+ * Assigns the same {@link TlsConfig} for all hosts.
+ *
+ * @since 5.2
+ */
+ public final PoolingAsyncClientConnectionManagerBuilder setDefaultTlsConfig(final TlsConfig config) {
+ this.tlsConfigResolver = (host) -> config;
+ return this;
+ }
+
+ /**
+ * Assigns {@link Resolver} of {@link TlsConfig} on a per host basis.
+ *
+ * @since 5.2
+ */
+ public final PoolingAsyncClientConnectionManagerBuilder setTlsConfigResolver(
+ final Resolver tlsConfigResolver) {
+ this.tlsConfigResolver = tlsConfigResolver;
+ return this;
+ }
/**
* Sets maximum time to live for persistent connections
@@ -232,6 +255,7 @@ public PoolingAsyncClientConnectionManager build() {
schemePortResolver,
dnsResolver);
poolingmgr.setConnectionConfigResolver(connectionConfigResolver);
+ poolingmgr.setTlsConfigResolver(tlsConfigResolver);
if (maxConnTotal > 0) {
poolingmgr.setMaxTotal(maxConnTotal);
}
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/io/HttpClientConnectionOperator.java b/httpclient5/src/main/java/org/apache/hc/client5/http/io/HttpClientConnectionOperator.java
index d1bf4fa92..f533fef22 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/io/HttpClientConnectionOperator.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/io/HttpClientConnectionOperator.java
@@ -37,6 +37,7 @@
import org.apache.hc.core5.http.io.SocketConfig;
import org.apache.hc.core5.http.protocol.HttpContext;
import org.apache.hc.core5.util.TimeValue;
+import org.apache.hc.core5.util.Timeout;
/**
* Connection operator that performs connection connect and upgrade operations.
@@ -65,6 +66,30 @@ void connect(
SocketConfig socketConfig,
HttpContext context) throws IOException;
+ /**
+ * Connect the given managed connection to the remote endpoint.
+ *
+ * @param conn the managed connection.
+ * @param host the address of the opposite endpoint.
+ * @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
+ */
+ default void connect(
+ ManagedHttpClientConnection conn,
+ HttpHost host,
+ InetSocketAddress localAddress,
+ Timeout connectTimeout,
+ SocketConfig socketConfig,
+ Object attachment,
+ HttpContext context) throws IOException {
+ connect(conn, host, localAddress, connectTimeout, socketConfig, context);
+ }
+
/**
* Upgrades transport security of the given managed connection
* by using the TLS security protocol.
@@ -78,4 +103,23 @@ void upgrade(
HttpHost host,
HttpContext context) throws IOException;
+ /**
+ * 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 connect request attachment.
+ * @param context the execution context.
+ *
+ * @since 5.2
+ */
+ default void upgrade(
+ ManagedHttpClientConnection conn,
+ HttpHost host,
+ Object attachment,
+ HttpContext context) throws IOException {
+ upgrade(conn, host, context);
+ }
+
}
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/nio/AsyncClientConnectionOperator.java b/httpclient5/src/main/java/org/apache/hc/client5/http/nio/AsyncClientConnectionOperator.java
index af1260429..f368e79ee 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/nio/AsyncClientConnectionOperator.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/nio/AsyncClientConnectionOperator.java
@@ -67,7 +67,6 @@ Future connect(
Object attachment,
FutureCallback callback);
-
/**
* Upgrades transport security of the given managed connection
* by using the TLS security protocol.
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/socket/ConnectionSocketFactory.java b/httpclient5/src/main/java/org/apache/hc/client5/http/socket/ConnectionSocketFactory.java
index 88cafd07c..f8d2e6fa2 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/socket/ConnectionSocketFactory.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/socket/ConnectionSocketFactory.java
@@ -36,6 +36,7 @@
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.protocol.HttpContext;
import org.apache.hc.core5.util.TimeValue;
+import org.apache.hc.core5.util.Timeout;
/**
* A factory for creating and connecting connection sockets.
@@ -81,4 +82,35 @@ Socket connectSocket(
InetSocketAddress localAddress,
HttpContext context) throws IOException;
+ /**
+ * Connects the socket to the target host with the given resolved remote address.
+ *
+ * @param socket the socket to connect, as obtained from {@link #createSocket(HttpContext)}.
+ * {@code null} indicates that a new socket should be created and connected.
+ * @param host target host as specified by the caller (end user).
+ * @param remoteAddress the resolved remote address to connect to.
+ * @param localAddress the local address to bind the socket to, or {@code null} for any.
+ * @param connectTimeout connect timeout.
+ * @param attachment connect request attachment.
+ * @param context the actual HTTP context.
+ *
+ * @return the connected socket. The returned object may be different
+ * from the {@code sock} argument if this factory supports
+ * a layered protocol.
+ *
+ * @throws IOException if an I/O error occurs
+ *
+ * @since 5.2
+ */
+ default Socket connectSocket(
+ Socket socket,
+ HttpHost host,
+ InetSocketAddress remoteAddress,
+ InetSocketAddress localAddress,
+ Timeout connectTimeout,
+ Object attachment,
+ HttpContext context) throws IOException {
+ return connectSocket(connectTimeout, socket, host, remoteAddress, localAddress, context);
+ }
+
}
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/socket/LayeredConnectionSocketFactory.java b/httpclient5/src/main/java/org/apache/hc/client5/http/socket/LayeredConnectionSocketFactory.java
index d35c296e1..36dfa80f8 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/socket/LayeredConnectionSocketFactory.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/socket/LayeredConnectionSocketFactory.java
@@ -62,4 +62,30 @@ Socket createLayeredSocket(
int port,
HttpContext context) throws IOException;
+ /**
+ * Returns a socket connected to the given host that is layered over an
+ * existing socket. Used primarily for creating secure sockets through
+ * proxies.
+ *
+ * @param socket the existing socket
+ * @param target the name of the target host.
+ * @param port the port to connect to on the target host.
+ * @param context the actual HTTP context.
+ * @param attachment connect request attachment.
+ *
+ * @return Socket a new socket
+ *
+ * @throws IOException if an I/O error occurs while creating the socket
+ *
+ * @since 5.2
+ */
+ default Socket createLayeredSocket(
+ Socket socket,
+ String target,
+ int port,
+ Object attachment,
+ HttpContext context) throws IOException {
+ return createLayeredSocket(socket, target, port, context);
+ }
+
}
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/AbstractClientTlsStrategy.java b/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/AbstractClientTlsStrategy.java
index 45a66f71b..21c72c34a 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/AbstractClientTlsStrategy.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/AbstractClientTlsStrategy.java
@@ -38,6 +38,7 @@
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSession;
+import org.apache.hc.client5.http.config.TlsConfig;
import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.concurrent.FutureCallback;
@@ -109,17 +110,23 @@ public void upgrade(
final FutureCallback callback) {
tlsSession.startTls(sslContext, endpoint, sslBufferManagement, (e, sslEngine) -> {
- final HttpVersionPolicy versionPolicy = attachment instanceof HttpVersionPolicy ?
- (HttpVersionPolicy) attachment : HttpVersionPolicy.NEGOTIATE;
+ final TlsConfig tlsConfig = attachment instanceof TlsConfig ? (TlsConfig) attachment : TlsConfig.DEFAULT;
+ final HttpVersionPolicy versionPolicy = tlsConfig.getHttpVersionPolicy();
final SSLParameters sslParameters = sslEngine.getSSLParameters();
+ final String[] supportedProtocols = tlsConfig.getSupportedProtocols();
if (supportedProtocols != null) {
sslParameters.setProtocols(supportedProtocols);
+ } else if (this.supportedProtocols != null) {
+ sslParameters.setProtocols(this.supportedProtocols);
} else if (versionPolicy != HttpVersionPolicy.FORCE_HTTP_1) {
sslParameters.setProtocols(TLS.excludeWeak(sslParameters.getProtocols()));
}
+ final String[] supportedCipherSuites = tlsConfig.getSupportedCipherSuites();
if (supportedCipherSuites != null) {
sslParameters.setCipherSuites(supportedCipherSuites);
+ } else if (this.supportedCipherSuites != null) {
+ sslParameters.setCipherSuites(this.supportedCipherSuites);
} else if (versionPolicy == HttpVersionPolicy.FORCE_HTTP_2) {
sslParameters.setCipherSuites(TlsCiphers.excludeH2Blacklisted(sslParameters.getCipherSuites()));
}
@@ -135,6 +142,7 @@ public void upgrade(
if (LOG.isDebugEnabled()) {
LOG.debug("Enabled protocols: {}", Arrays.asList(sslEngine.getEnabledProtocols()));
LOG.debug("Enabled cipher suites:{}", Arrays.asList(sslEngine.getEnabledCipherSuites()));
+ LOG.debug("Starting handshake ({})", handshakeTimeout);
}
}, (e, sslEngine) -> {
verifySession(endpoint.getHostName(), sslEngine.getSession());
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/SSLConnectionSocketFactory.java b/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/SSLConnectionSocketFactory.java
index 2a29e91c3..59a8df5f6 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/SSLConnectionSocketFactory.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/SSLConnectionSocketFactory.java
@@ -47,6 +47,7 @@
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
+import org.apache.hc.client5.http.config.TlsConfig;
import org.apache.hc.client5.http.socket.LayeredConnectionSocketFactory;
import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
@@ -60,6 +61,7 @@
import org.apache.hc.core5.util.Args;
import org.apache.hc.core5.util.Asserts;
import org.apache.hc.core5.util.TimeValue;
+import org.apache.hc.core5.util.Timeout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -200,6 +202,19 @@ public Socket connectSocket(
final InetSocketAddress remoteAddress,
final InetSocketAddress localAddress,
final HttpContext context) throws IOException {
+ final Timeout timeout = connectTimeout != null ? Timeout.of(connectTimeout.getDuration(), connectTimeout.getTimeUnit()) : null;
+ return connectSocket(socket, host, remoteAddress, localAddress, timeout, timeout, context);
+ }
+
+ @Override
+ public Socket connectSocket(
+ final Socket socket,
+ final HttpHost host,
+ final InetSocketAddress remoteAddress,
+ final InetSocketAddress localAddress,
+ final Timeout connectTimeout,
+ final Object attachment,
+ final HttpContext context) throws IOException {
Args.notNull(host, "HTTP host");
Args.notNull(remoteAddress, "Remote address");
final Socket sock = socket != null ? socket : createSocket(context);
@@ -214,7 +229,7 @@ public Socket connectSocket(
// only to this library
try {
AccessController.doPrivileged((PrivilegedExceptionAction) () -> {
- sock.connect(remoteAddress, connectTimeout != null ? connectTimeout.toMillisecondsIntBound() : 0);
+ sock.connect(remoteAddress, Timeout.defaultsToDisabled(connectTimeout).toMillisecondsIntBound());
return null;
});
} catch (final PrivilegedActionException e) {
@@ -230,12 +245,10 @@ public Socket connectSocket(
// Setup SSL layering if necessary
if (sock instanceof SSLSocket) {
final SSLSocket sslsock = (SSLSocket) sock;
- LOG.debug("Starting handshake");
- sslsock.startHandshake();
- verifyHostname(sslsock, host.getHostName());
+ executeHandshake(sslsock, host.getHostName(), attachment);
return sock;
}
- return createLayeredSocket(sock, host.getHostName(), remoteAddress.getPort(), context);
+ return createLayeredSocket(sock, host.getHostName(), remoteAddress.getPort(), attachment, context);
}
@Override
@@ -244,11 +257,27 @@ public Socket createLayeredSocket(
final String target,
final int port,
final HttpContext context) throws IOException {
+ return createLayeredSocket(socket, target, port, context);
+ }
+
+ @Override
+ public Socket createLayeredSocket(
+ final Socket socket,
+ final String target,
+ final int port,
+ final Object attachment,
+ final HttpContext context) throws IOException {
final SSLSocket sslsock = (SSLSocket) this.socketFactory.createSocket(
socket,
target,
port,
true);
+ executeHandshake(sslsock, target, attachment);
+ return sslsock;
+ }
+
+ private void executeHandshake(final SSLSocket sslsock, final String target, final Object attachment) throws IOException {
+ final TlsConfig tlsConfig = attachment instanceof TlsConfig ? (TlsConfig) attachment : TlsConfig.DEFAULT;
if (supportedProtocols != null) {
sslsock.setEnabledProtocols(supportedProtocols);
} else {
@@ -259,17 +288,20 @@ public Socket createLayeredSocket(
} else {
sslsock.setEnabledCipherSuites(TlsCiphers.excludeWeak(sslsock.getEnabledCipherSuites()));
}
+ final Timeout handshakeTimeout = tlsConfig.getHandshakeTimeout();
+ if (handshakeTimeout != null) {
+ sslsock.setSoTimeout(handshakeTimeout.toMillisecondsIntBound());
+ }
+
+ prepareSocket(sslsock);
if (LOG.isDebugEnabled()) {
LOG.debug("Enabled protocols: {}", (Object) sslsock.getEnabledProtocols());
LOG.debug("Enabled cipher suites: {}", (Object) sslsock.getEnabledCipherSuites());
+ LOG.debug("Starting handshake ({})", handshakeTimeout);
}
-
- prepareSocket(sslsock);
- LOG.debug("Starting handshake");
sslsock.startHandshake();
verifyHostname(sslsock, target);
- return sslsock;
}
private void verifyHostname(final SSLSocket sslsock, final String hostname) throws IOException {
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientFullDuplexExchange.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientFullDuplexExchange.java
index a396ca322..a30661cd6 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientFullDuplexExchange.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientFullDuplexExchange.java
@@ -52,11 +52,9 @@
import org.apache.hc.core5.http.nio.support.BasicResponseConsumer;
import org.apache.hc.core5.http.protocol.HttpContext;
import org.apache.hc.core5.http.support.BasicRequestBuilder;
-import org.apache.hc.core5.http2.HttpVersionPolicy;
import org.apache.hc.core5.http2.config.H2Config;
import org.apache.hc.core5.io.CloseMode;
import org.apache.hc.core5.reactor.IOReactorConfig;
-import org.apache.hc.core5.util.Timeout;
/**
* This example demonstrates a full-duplex, streaming HTTP/1.1 message exchange.
@@ -65,15 +63,10 @@ public class AsyncClientFullDuplexExchange {
public static void main(final String[] args) throws Exception {
- final IOReactorConfig ioReactorConfig = IOReactorConfig.custom()
- .setSoTimeout(Timeout.ofSeconds(5))
- .build();
-
final MinimalHttpAsyncClient client = HttpAsyncClients.createMinimal(
- HttpVersionPolicy.NEGOTIATE,
H2Config.DEFAULT,
Http1Config.DEFAULT,
- ioReactorConfig);
+ IOReactorConfig.DEFAULT);
client.start();
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientH2FullDuplexExchange.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientH2FullDuplexExchange.java
index aa90bb214..b221c7ff5 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientH2FullDuplexExchange.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientH2FullDuplexExchange.java
@@ -32,13 +32,16 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import org.apache.hc.client5.http.config.TlsConfig;
import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
import org.apache.hc.client5.http.impl.async.MinimalHttpAsyncClient;
+import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.EntityDetails;
import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpException;
import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.http.config.Http1Config;
import org.apache.hc.core5.http.message.BasicHttpRequest;
import org.apache.hc.core5.http.message.StatusLine;
import org.apache.hc.core5.http.nio.AsyncClientExchangeHandler;
@@ -55,7 +58,6 @@
import org.apache.hc.core5.http2.config.H2Config;
import org.apache.hc.core5.io.CloseMode;
import org.apache.hc.core5.reactor.IOReactorConfig;
-import org.apache.hc.core5.util.Timeout;
/**
* This example demonstrates a full-duplex, streaming HTTP/2 message exchange.
@@ -64,12 +66,15 @@ public class AsyncClientH2FullDuplexExchange {
public static void main(final String[] args) throws Exception {
- final IOReactorConfig ioReactorConfig = IOReactorConfig.custom()
- .setSoTimeout(Timeout.ofSeconds(5))
- .build();
-
final MinimalHttpAsyncClient client = HttpAsyncClients.createMinimal(
- HttpVersionPolicy.FORCE_HTTP_2, H2Config.DEFAULT, null, ioReactorConfig);
+ H2Config.DEFAULT,
+ Http1Config.DEFAULT,
+ IOReactorConfig.DEFAULT,
+ PoolingAsyncClientConnectionManagerBuilder.create()
+ .setDefaultTlsConfig(TlsConfig.custom()
+ .setVersionPolicy(HttpVersionPolicy.FORCE_HTTP_2)
+ .build())
+ .build());
client.start();
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientH2Multiplexing.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientH2Multiplexing.java
index 9a4077fb1..442dc669f 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientH2Multiplexing.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientH2Multiplexing.java
@@ -35,17 +35,19 @@
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.config.TlsConfig;
import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
import org.apache.hc.client5.http.impl.async.MinimalHttpAsyncClient;
+import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
import org.apache.hc.core5.concurrent.FutureCallback;
import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.config.Http1Config;
import org.apache.hc.core5.http.message.StatusLine;
import org.apache.hc.core5.http.nio.AsyncClientEndpoint;
import org.apache.hc.core5.http2.HttpVersionPolicy;
import org.apache.hc.core5.http2.config.H2Config;
import org.apache.hc.core5.io.CloseMode;
import org.apache.hc.core5.reactor.IOReactorConfig;
-import org.apache.hc.core5.util.Timeout;
/**
* This example demonstrates concurrent (multiplexed) execution of multiple
@@ -55,12 +57,15 @@ public class AsyncClientH2Multiplexing {
public static void main(final String[] args) throws Exception {
- final IOReactorConfig ioReactorConfig = IOReactorConfig.custom()
- .setSoTimeout(Timeout.ofSeconds(5))
- .build();
-
final MinimalHttpAsyncClient client = HttpAsyncClients.createMinimal(
- HttpVersionPolicy.FORCE_HTTP_2, H2Config.DEFAULT, null, ioReactorConfig);
+ H2Config.DEFAULT,
+ Http1Config.DEFAULT,
+ IOReactorConfig.DEFAULT,
+ PoolingAsyncClientConnectionManagerBuilder.create()
+ .setDefaultTlsConfig(TlsConfig.custom()
+ .setVersionPolicy(HttpVersionPolicy.FORCE_HTTP_2)
+ .build())
+ .build());
client.start();
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientH2ServerPush.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientH2ServerPush.java
index 2881d9b0a..dc36ade3d 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientH2ServerPush.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientH2ServerPush.java
@@ -33,8 +33,10 @@
import org.apache.hc.client5.http.async.methods.AbstractBinPushConsumer;
import org.apache.hc.client5.http.async.methods.AbstractCharResponseConsumer;
+import org.apache.hc.client5.http.config.TlsConfig;
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
+import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.HttpException;
import org.apache.hc.core5.http.HttpRequest;
@@ -46,8 +48,6 @@
import org.apache.hc.core5.http2.HttpVersionPolicy;
import org.apache.hc.core5.http2.config.H2Config;
import org.apache.hc.core5.io.CloseMode;
-import org.apache.hc.core5.reactor.IOReactorConfig;
-import org.apache.hc.core5.util.Timeout;
/**
* This example demonstrates handling of HTTP/2 message exchanges pushed by the server.
@@ -56,18 +56,15 @@ public class AsyncClientH2ServerPush {
public static void main(final String[] args) throws Exception {
- final IOReactorConfig ioReactorConfig = IOReactorConfig.custom()
- .setSoTimeout(Timeout.ofSeconds(5))
- .build();
-
- final H2Config h2Config = H2Config.custom()
- .setPushEnabled(true)
- .build();
-
final CloseableHttpAsyncClient client = HttpAsyncClients.custom()
- .setIOReactorConfig(ioReactorConfig)
- .setVersionPolicy(HttpVersionPolicy.FORCE_HTTP_2)
- .setH2Config(h2Config)
+ .setH2Config(H2Config.custom()
+ .setPushEnabled(true)
+ .build())
+ .setConnectionManager(PoolingAsyncClientConnectionManagerBuilder.create()
+ .setDefaultTlsConfig(TlsConfig.custom()
+ .setVersionPolicy(HttpVersionPolicy.FORCE_HTTP_2)
+ .build())
+ .build())
.build();
client.start();
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientHttp1Pipelining.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientHttp1Pipelining.java
index 548c4ed1e..4e9395583 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientHttp1Pipelining.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientHttp1Pipelining.java
@@ -35,17 +35,19 @@
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.config.TlsConfig;
import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
import org.apache.hc.client5.http.impl.async.MinimalHttpAsyncClient;
+import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
import org.apache.hc.core5.concurrent.FutureCallback;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.config.Http1Config;
import org.apache.hc.core5.http.message.StatusLine;
import org.apache.hc.core5.http.nio.AsyncClientEndpoint;
import org.apache.hc.core5.http2.HttpVersionPolicy;
+import org.apache.hc.core5.http2.config.H2Config;
import org.apache.hc.core5.io.CloseMode;
import org.apache.hc.core5.reactor.IOReactorConfig;
-import org.apache.hc.core5.util.Timeout;
/**
* This example demonstrates pipelined execution of multiple HTTP/1.1 message exchanges.
@@ -54,12 +56,15 @@ public class AsyncClientHttp1Pipelining {
public static void main(final String[] args) throws Exception {
- final IOReactorConfig ioReactorConfig = IOReactorConfig.custom()
- .setSoTimeout(Timeout.ofSeconds(5))
- .build();
-
final MinimalHttpAsyncClient client = HttpAsyncClients.createMinimal(
- HttpVersionPolicy.FORCE_HTTP_1, null, Http1Config.DEFAULT, ioReactorConfig);
+ H2Config.DEFAULT,
+ Http1Config.DEFAULT,
+ IOReactorConfig.DEFAULT,
+ PoolingAsyncClientConnectionManagerBuilder.create()
+ .setDefaultTlsConfig(TlsConfig.custom()
+ .setVersionPolicy(HttpVersionPolicy.FORCE_HTTP_1)
+ .build())
+ .build());
client.start();
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientTlsAlpn.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientTlsAlpn.java
index 22c1e377b..97db267b7 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientTlsAlpn.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientTlsAlpn.java
@@ -45,7 +45,6 @@
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.message.StatusLine;
import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
-import org.apache.hc.core5.http2.HttpVersionPolicy;
import org.apache.hc.core5.io.CloseMode;
/**
@@ -74,7 +73,6 @@ public TlsDetails create(final SSLEngine sslEngine) {
.setTlsStrategy(tlsStrategy)
.build();
try (final CloseableHttpAsyncClient client = HttpAsyncClients.custom()
- .setVersionPolicy(HttpVersionPolicy.NEGOTIATE)
.setConnectionManager(cm)
.build()) {
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ReactiveClientFullDuplexExchange.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ReactiveClientFullDuplexExchange.java
index 9bb6630a0..e4fcf5644 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ReactiveClientFullDuplexExchange.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ReactiveClientFullDuplexExchange.java
@@ -40,13 +40,11 @@
import org.apache.hc.core5.http.Message;
import org.apache.hc.core5.http.config.Http1Config;
import org.apache.hc.core5.http.nio.support.BasicRequestProducer;
-import org.apache.hc.core5.http2.HttpVersionPolicy;
import org.apache.hc.core5.http2.config.H2Config;
import org.apache.hc.core5.io.CloseMode;
import org.apache.hc.core5.reactive.ReactiveEntityProducer;
import org.apache.hc.core5.reactive.ReactiveResponseConsumer;
import org.apache.hc.core5.reactor.IOReactorConfig;
-import org.apache.hc.core5.util.Timeout;
import org.reactivestreams.Publisher;
import io.reactivex.Flowable;
@@ -59,15 +57,10 @@ public class ReactiveClientFullDuplexExchange {
public static void main(final String[] args) throws Exception {
- final IOReactorConfig ioReactorConfig = IOReactorConfig.custom()
- .setSoTimeout(Timeout.ofSeconds(5))
- .build();
-
final MinimalHttpAsyncClient client = HttpAsyncClients.createMinimal(
- HttpVersionPolicy.NEGOTIATE,
H2Config.DEFAULT,
Http1Config.DEFAULT,
- ioReactorConfig);
+ IOReactorConfig.DEFAULT);
client.start();
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/io/TestBasicHttpClientConnectionManager.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/io/TestBasicHttpClientConnectionManager.java
index 76f199d77..1733f4ebf 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/io/TestBasicHttpClientConnectionManager.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/io/TestBasicHttpClientConnectionManager.java
@@ -30,10 +30,13 @@
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
+import java.util.concurrent.TimeUnit;
import org.apache.hc.client5.http.DnsResolver;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.SchemePortResolver;
+import org.apache.hc.client5.http.config.ConnectionConfig;
+import org.apache.hc.client5.http.config.TlsConfig;
import org.apache.hc.client5.http.io.ConnectionEndpoint;
import org.apache.hc.client5.http.io.LeaseRequest;
import org.apache.hc.client5.http.io.ManagedHttpClientConnection;
@@ -361,26 +364,55 @@ public void testTargetConnect() throws Exception {
mgr.setSocketConfig(sconfig);
+ final ConnectionConfig connectionConfig = ConnectionConfig.custom()
+ .setConnectTimeout(234, TimeUnit.MILLISECONDS)
+ .build();
+ mgr.setConnectionConfig(connectionConfig);
+ final TlsConfig tlsConfig = TlsConfig.custom()
+ .setHandshakeTimeout(345, TimeUnit.MILLISECONDS)
+ .build();
+ mgr.setTlsConfig(tlsConfig);
+
Mockito.when(dnsResolver.resolve("somehost")).thenReturn(new InetAddress[] {remote});
Mockito.when(schemePortResolver.resolve(target)).thenReturn(8443);
Mockito.when(socketFactoryRegistry.lookup("https")).thenReturn(plainSocketFactory);
Mockito.when(plainSocketFactory.createSocket(Mockito.any())).thenReturn(socket);
Mockito.when(plainSocketFactory.connectSocket(
- Mockito.any(),
Mockito.eq(socket),
Mockito.any(),
Mockito.any(),
Mockito.any(),
+ Mockito.any(),
+ Mockito.any(),
Mockito.any())).thenReturn(socket);
- mgr.connect(endpoint1, TimeValue.ofMilliseconds(123), context);
+ mgr.connect(endpoint1, null, context);
Mockito.verify(dnsResolver, Mockito.times(1)).resolve("somehost");
Mockito.verify(schemePortResolver, Mockito.times(1)).resolve(target);
Mockito.verify(plainSocketFactory, Mockito.times(1)).createSocket(context);
- Mockito.verify(plainSocketFactory, Mockito.times(1)).connectSocket(TimeValue.ofMilliseconds(123), socket, target,
+ Mockito.verify(plainSocketFactory, Mockito.times(1)).connectSocket(
+ socket,
+ target,
new InetSocketAddress(remote, 8443),
- new InetSocketAddress(local, 0), context);
+ new InetSocketAddress(local, 0),
+ Timeout.ofMilliseconds(234),
+ tlsConfig,
+ context);
+
+ mgr.connect(endpoint1, TimeValue.ofMilliseconds(123), context);
+
+ Mockito.verify(dnsResolver, Mockito.times(2)).resolve("somehost");
+ Mockito.verify(schemePortResolver, Mockito.times(2)).resolve(target);
+ Mockito.verify(plainSocketFactory, Mockito.times(2)).createSocket(context);
+ Mockito.verify(plainSocketFactory, Mockito.times(1)).connectSocket(
+ socket,
+ target,
+ new InetSocketAddress(remote, 8443),
+ new InetSocketAddress(local, 0),
+ Timeout.ofMilliseconds(123),
+ tlsConfig,
+ context);
}
@Test
@@ -402,6 +434,15 @@ public void testProxyConnectAndUpgrade() throws Exception {
mgr.setSocketConfig(sconfig);
+ final ConnectionConfig connectionConfig = ConnectionConfig.custom()
+ .setConnectTimeout(234, TimeUnit.MILLISECONDS)
+ .build();
+ mgr.setConnectionConfig(connectionConfig);
+ final TlsConfig tlsConfig = TlsConfig.custom()
+ .setHandshakeTimeout(345, TimeUnit.MILLISECONDS)
+ .build();
+ mgr.setTlsConfig(tlsConfig);
+
Mockito.when(dnsResolver.resolve("someproxy")).thenReturn(new InetAddress[] {remote});
Mockito.when(schemePortResolver.resolve(proxy)).thenReturn(8080);
Mockito.when(schemePortResolver.resolve(target)).thenReturn(8443);
@@ -409,21 +450,27 @@ public void testProxyConnectAndUpgrade() throws Exception {
Mockito.when(socketFactoryRegistry.lookup("https")).thenReturn(sslSocketFactory);
Mockito.when(plainSocketFactory.createSocket(Mockito.any())).thenReturn(socket);
Mockito.when(plainSocketFactory.connectSocket(
- Mockito.any(),
Mockito.eq(socket),
Mockito.any(),
Mockito.any(),
Mockito.any(),
+ Mockito.any(),
+ Mockito.any(),
Mockito.any())).thenReturn(socket);
- mgr.connect(endpoint1, TimeValue.ofMilliseconds(123), context);
+ mgr.connect(endpoint1, null, context);
Mockito.verify(dnsResolver, Mockito.times(1)).resolve("someproxy");
Mockito.verify(schemePortResolver, Mockito.times(1)).resolve(proxy);
Mockito.verify(plainSocketFactory, Mockito.times(1)).createSocket(context);
- Mockito.verify(plainSocketFactory, Mockito.times(1)).connectSocket(TimeValue.ofMilliseconds(123), socket, proxy,
+ Mockito.verify(plainSocketFactory, Mockito.times(1)).connectSocket(
+ socket,
+ proxy,
new InetSocketAddress(remote, 8080),
- new InetSocketAddress(local, 0), context);
+ new InetSocketAddress(local, 0),
+ Timeout.ofMilliseconds(234),
+ tlsConfig,
+ context);
Mockito.when(conn.getSocket()).thenReturn(socket);
@@ -431,7 +478,7 @@ public void testProxyConnectAndUpgrade() throws Exception {
Mockito.verify(schemePortResolver, Mockito.times(1)).resolve(target);
Mockito.verify(sslSocketFactory, Mockito.times(1)).createLayeredSocket(
- socket, "somehost", 8443, context);
+ socket, "somehost", 8443, tlsConfig, context);
}
}
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/io/TestHttpClientConnectionOperator.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/io/TestHttpClientConnectionOperator.java
index 34bb77a58..f83c787dc 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/io/TestHttpClientConnectionOperator.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/io/TestHttpClientConnectionOperator.java
@@ -39,6 +39,7 @@
import org.apache.hc.client5.http.HttpHostConnectException;
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.io.ManagedHttpClientConnection;
import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
import org.apache.hc.client5.http.socket.LayeredConnectionSocketFactory;
@@ -48,6 +49,7 @@
import org.apache.hc.core5.http.protocol.BasicHttpContext;
import org.apache.hc.core5.http.protocol.HttpContext;
import org.apache.hc.core5.util.TimeValue;
+import org.apache.hc.core5.util.Timeout;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -96,6 +98,7 @@ public void testConnect() throws Exception {
Mockito.any(),
Mockito.any(),
Mockito.any(),
+ Mockito.any(),
Mockito.any())).thenReturn(socket);
final SocketConfig socketConfig = SocketConfig.custom()
@@ -105,8 +108,11 @@ public void testConnect() throws Exception {
.setTcpNoDelay(true)
.setSoLinger(50, TimeUnit.MILLISECONDS)
.build();
+ final TlsConfig tlsConfig = TlsConfig.custom()
+ .build();
final InetSocketAddress localAddress = new InetSocketAddress(local, 0);
- connectionOperator.connect(conn, host, localAddress, TimeValue.ofMilliseconds(1000), socketConfig, context);
+ connectionOperator.connect(conn, host, localAddress,
+ Timeout.ofMilliseconds(123), socketConfig, tlsConfig, context);
Mockito.verify(socket).setKeepAlive(true);
Mockito.verify(socket).setReuseAddress(true);
@@ -115,11 +121,12 @@ public void testConnect() throws Exception {
Mockito.verify(socket).setTcpNoDelay(true);
Mockito.verify(plainSocketFactory).connectSocket(
- TimeValue.ofMilliseconds(1000),
socket,
host,
new InetSocketAddress(ip1, 80),
localAddress,
+ Timeout.ofMilliseconds(123),
+ tlsConfig,
context);
Mockito.verify(conn, Mockito.times(2)).bind(socket);
}
@@ -141,6 +148,7 @@ public void testConnectTimeout() throws Exception {
Mockito.any(),
Mockito.any(),
Mockito.any(),
+ Mockito.any(),
Mockito.any())).thenThrow(new SocketTimeoutException());
Assert.assertThrows(ConnectTimeoutException.class, () ->
@@ -165,6 +173,7 @@ public void testConnectFailure() throws Exception {
Mockito.any(),
Mockito.any(),
Mockito.any(),
+ Mockito.any(),
Mockito.any())).thenThrow(new ConnectException());
Assert.assertThrows(HttpHostConnectException.class, () ->
@@ -185,29 +194,35 @@ public void testConnectFailover() throws Exception {
Mockito.when(schemePortResolver.resolve(host)).thenReturn(80);
Mockito.when(plainSocketFactory.createSocket(Mockito.any())).thenReturn(socket);
Mockito.when(plainSocketFactory.connectSocket(
- Mockito.any(),
Mockito.any(),
Mockito.any(),
Mockito.eq(new InetSocketAddress(ip1, 80)),
Mockito.any(),
+ Mockito.any(),
+ Mockito.any(),
Mockito.any())).thenThrow(new ConnectException());
Mockito.when(plainSocketFactory.connectSocket(
- Mockito.any(),
Mockito.any(),
Mockito.any(),
Mockito.eq(new InetSocketAddress(ip2, 80)),
Mockito.any(),
+ Mockito.any(),
+ Mockito.any(),
Mockito.any())).thenReturn(socket);
final InetSocketAddress localAddress = new InetSocketAddress(local, 0);
- connectionOperator.connect(conn, host, localAddress, TimeValue.ofMilliseconds(1000), SocketConfig.DEFAULT, context);
+ final TlsConfig tlsConfig = TlsConfig.custom()
+ .build();
+ connectionOperator.connect(conn, host, localAddress,
+ Timeout.ofMilliseconds(123), SocketConfig.DEFAULT, tlsConfig, context);
Mockito.verify(plainSocketFactory).connectSocket(
- TimeValue.ofMilliseconds(1000),
socket,
host,
new InetSocketAddress(ip2, 80),
localAddress,
+ Timeout.ofMilliseconds(123),
+ tlsConfig,
context);
Mockito.verify(conn, Mockito.times(3)).bind(socket);
}
@@ -228,17 +243,22 @@ public void testConnectExplicitAddress() throws Exception {
Mockito.any(),
Mockito.any(),
Mockito.any(),
+ Mockito.any(),
Mockito.any())).thenReturn(socket);
final InetSocketAddress localAddress = new InetSocketAddress(local, 0);
- connectionOperator.connect(conn, host, localAddress, TimeValue.ofMilliseconds(1000), SocketConfig.DEFAULT, context);
+ final TlsConfig tlsConfig = TlsConfig.custom()
+ .build();
+ connectionOperator.connect(conn, host, localAddress,
+ Timeout.ofMilliseconds(123), SocketConfig.DEFAULT, tlsConfig, context);
Mockito.verify(plainSocketFactory).connectSocket(
- TimeValue.ofMilliseconds(1000),
socket,
host,
new InetSocketAddress(ip, 80),
localAddress,
+ Timeout.ofMilliseconds(123),
+ tlsConfig,
context);
Mockito.verify(dnsResolver, Mockito.never()).resolve(Mockito.anyString());
Mockito.verify(conn, Mockito.times(2)).bind(socket);
@@ -258,9 +278,10 @@ public void testUpgrade() throws Exception {
Mockito.any(),
Mockito.eq("somehost"),
Mockito.eq(443),
+ Mockito.eq(Timeout.ofMilliseconds(345)),
Mockito.any())).thenReturn(socket);
- connectionOperator.upgrade(conn, host, context);
+ connectionOperator.upgrade(conn, host, Timeout.ofMilliseconds(345), context);
Mockito.verify(conn).bind(socket);
}
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/io/TestPoolingHttpClientConnectionManager.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/io/TestPoolingHttpClientConnectionManager.java
index 29dbdd9b9..f837d2840 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/io/TestPoolingHttpClientConnectionManager.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/io/TestPoolingHttpClientConnectionManager.java
@@ -37,6 +37,8 @@
import org.apache.hc.client5.http.DnsResolver;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.SchemePortResolver;
+import org.apache.hc.client5.http.config.ConnectionConfig;
+import org.apache.hc.client5.http.config.TlsConfig;
import org.apache.hc.client5.http.io.ConnectionEndpoint;
import org.apache.hc.client5.http.io.LeaseRequest;
import org.apache.hc.client5.http.io.ManagedHttpClientConnection;
@@ -247,26 +249,55 @@ public void testTargetConnect() throws Exception {
mgr.setDefaultSocketConfig(sconfig);
+ final ConnectionConfig connectionConfig = ConnectionConfig.custom()
+ .setConnectTimeout(234, TimeUnit.MILLISECONDS)
+ .build();
+ mgr.setDefaultConnectionConfig(connectionConfig);
+ final TlsConfig tlsConfig = TlsConfig.custom()
+ .setHandshakeTimeout(345, TimeUnit.MILLISECONDS)
+ .build();
+ mgr.setDefaultTlsConfig(tlsConfig);
+
Mockito.when(dnsResolver.resolve("somehost")).thenReturn(new InetAddress[]{remote});
Mockito.when(schemePortResolver.resolve(target)).thenReturn(8443);
Mockito.when(socketFactoryRegistry.lookup("https")).thenReturn(plainSocketFactory);
Mockito.when(plainSocketFactory.createSocket(Mockito.any())).thenReturn(socket);
Mockito.when(plainSocketFactory.connectSocket(
- Mockito.any(),
Mockito.eq(socket),
Mockito.any(),
Mockito.any(),
Mockito.any(),
+ Mockito.any(),
+ Mockito.any(),
Mockito.any())).thenReturn(socket);
- mgr.connect(endpoint1, TimeValue.ofMilliseconds(123), context);
+ mgr.connect(endpoint1, null, context);
Mockito.verify(dnsResolver, Mockito.times(1)).resolve("somehost");
Mockito.verify(schemePortResolver, Mockito.times(1)).resolve(target);
Mockito.verify(plainSocketFactory, Mockito.times(1)).createSocket(context);
- Mockito.verify(plainSocketFactory, Mockito.times(1)).connectSocket(TimeValue.ofMilliseconds(123), socket, target,
+ Mockito.verify(plainSocketFactory, Mockito.times(1)).connectSocket(
+ socket,
+ target,
new InetSocketAddress(remote, 8443),
- new InetSocketAddress(local, 0), context);
+ new InetSocketAddress(local, 0),
+ Timeout.ofMilliseconds(234),
+ tlsConfig,
+ context);
+
+ mgr.connect(endpoint1, TimeValue.ofMilliseconds(123), context);
+
+ Mockito.verify(dnsResolver, Mockito.times(2)).resolve("somehost");
+ Mockito.verify(schemePortResolver, Mockito.times(2)).resolve(target);
+ Mockito.verify(plainSocketFactory, Mockito.times(2)).createSocket(context);
+ Mockito.verify(plainSocketFactory, Mockito.times(1)).connectSocket(
+ socket,
+ target,
+ new InetSocketAddress(remote, 8443),
+ new InetSocketAddress(local, 0),
+ Timeout.ofMilliseconds(123),
+ tlsConfig,
+ context);
}
@Test
@@ -301,6 +332,15 @@ public void testProxyConnectAndUpgrade() throws Exception {
mgr.setDefaultSocketConfig(sconfig);
+ final ConnectionConfig connectionConfig = ConnectionConfig.custom()
+ .setConnectTimeout(234, TimeUnit.MILLISECONDS)
+ .build();
+ mgr.setDefaultConnectionConfig(connectionConfig);
+ final TlsConfig tlsConfig = TlsConfig.custom()
+ .setHandshakeTimeout(345, TimeUnit.MILLISECONDS)
+ .build();
+ mgr.setDefaultTlsConfig(tlsConfig);
+
Mockito.when(dnsResolver.resolve("someproxy")).thenReturn(new InetAddress[] {remote});
Mockito.when(schemePortResolver.resolve(proxy)).thenReturn(8080);
Mockito.when(schemePortResolver.resolve(target)).thenReturn(8443);
@@ -308,21 +348,27 @@ public void testProxyConnectAndUpgrade() throws Exception {
Mockito.when(socketFactoryRegistry.lookup("https")).thenReturn(sslsf);
Mockito.when(plainsf.createSocket(Mockito.any())).thenReturn(mockSock);
Mockito.when(plainsf.connectSocket(
- Mockito.any(),
Mockito.eq(mockSock),
Mockito.any(),
Mockito.any(),
Mockito.any(),
+ Mockito.any(),
+ Mockito.any(),
Mockito.any())).thenReturn(mockSock);
- mgr.connect(endpoint1, TimeValue.ofMilliseconds(123), context);
+ mgr.connect(endpoint1, null, context);
Mockito.verify(dnsResolver, Mockito.times(1)).resolve("someproxy");
Mockito.verify(schemePortResolver, Mockito.times(1)).resolve(proxy);
Mockito.verify(plainsf, Mockito.times(1)).createSocket(context);
- Mockito.verify(plainsf, Mockito.times(1)).connectSocket(TimeValue.ofMilliseconds(123), mockSock, proxy,
+ Mockito.verify(plainsf, Mockito.times(1)).connectSocket(
+ mockSock,
+ proxy,
new InetSocketAddress(remote, 8080),
- new InetSocketAddress(local, 0), context);
+ new InetSocketAddress(local, 0),
+ Timeout.ofMilliseconds(234),
+ tlsConfig,
+ context);
Mockito.when(conn.isOpen()).thenReturn(true);
Mockito.when(conn.getSocket()).thenReturn(mockSock);
@@ -331,7 +377,7 @@ public void testProxyConnectAndUpgrade() throws Exception {
Mockito.verify(schemePortResolver, Mockito.times(1)).resolve(target);
Mockito.verify(sslsf, Mockito.times(1)).createLayeredSocket(
- mockSock, "somehost", 8443, context);
+ mockSock, "somehost", 8443, tlsConfig, context);
}
}