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
index 7a014e263..45acdb96d 100644
--- 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
@@ -32,6 +32,7 @@ import java.util.concurrent.TimeUnit;
import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.http.ssl.TLS;
import org.apache.hc.core5.http2.HttpVersionPolicy;
import org.apache.hc.core5.util.Timeout;
@@ -166,6 +167,23 @@ public class TlsConfig implements Cloneable {
return this;
}
+ /**
+ * Determines supported TLS protocols.
+ *
+ * Default: {@code null} (undefined)
+ *
+ */
+ public Builder setSupportedProtocols(final TLS... supportedProtocols) {
+ this.supportedProtocols = new String[supportedProtocols.length];
+ for (int i = 0; i < supportedProtocols.length; i++) {
+ final TLS protocol = supportedProtocols[i];
+ if (protocol != null) {
+ this.supportedProtocols[i] = protocol.id;
+ }
+ }
+ return this;
+ }
+
/**
* Determines supported cipher suites.
*
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientConnectionConfig.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientConnectionConfig.java
new file mode 100644
index 000000000..7f2dd3a7b
--- /dev/null
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientConnectionConfig.java
@@ -0,0 +1,133 @@
+/*
+ * ====================================================================
+ * 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.examples;
+
+import java.util.concurrent.Future;
+
+import org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
+import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
+import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder;
+import org.apache.hc.client5.http.async.methods.SimpleRequestProducer;
+import org.apache.hc.client5.http.async.methods.SimpleResponseConsumer;
+import org.apache.hc.client5.http.config.ConnectionConfig;
+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.PoolingAsyncClientConnectionManager;
+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.URIScheme;
+import org.apache.hc.core5.http.message.StatusLine;
+import org.apache.hc.core5.http.ssl.TLS;
+import org.apache.hc.core5.io.CloseMode;
+import org.apache.hc.core5.util.TimeValue;
+import org.apache.hc.core5.util.Timeout;
+
+/**
+ * This example demonstrates how to use connection configuration on a per-route or a per-host
+ * basis.
+ */
+public class AsyncClientConnectionConfig {
+
+ public static void main(final String[] args) throws Exception {
+ final PoolingAsyncClientConnectionManager cm = PoolingAsyncClientConnectionManagerBuilder.create()
+ .setConnectionConfigResolver(route -> {
+ // Use different settings for all secure (TLS) connections
+ final HttpHost targetHost = route.getTargetHost();
+ if (route.isSecure()) {
+ return ConnectionConfig.custom()
+ .setConnectTimeout(Timeout.ofMinutes(2))
+ .setSocketTimeout(Timeout.ofMinutes(2))
+ .setValidateAfterInactivity(TimeValue.ofMinutes(1))
+ .setTimeToLive(TimeValue.ofHours(1))
+ .build();
+ } else {
+ return ConnectionConfig.custom()
+ .setConnectTimeout(Timeout.ofMinutes(1))
+ .setSocketTimeout(Timeout.ofMinutes(1))
+ .setValidateAfterInactivity(TimeValue.ofSeconds(15))
+ .setTimeToLive(TimeValue.ofMinutes(15))
+ .build();
+ }
+ })
+ .setTlsConfigResolver(host -> {
+ // Use different settings for specific hosts
+ if (host.getSchemeName().equalsIgnoreCase("httpbin.org")) {
+ return TlsConfig.custom()
+ .setSupportedProtocols(TLS.V_1_3)
+ .setHandshakeTimeout(Timeout.ofSeconds(10))
+ .build();
+ } else {
+ return TlsConfig.DEFAULT;
+ }
+ })
+ .build();
+ try (final CloseableHttpAsyncClient client = HttpAsyncClients.custom()
+ .setConnectionManager(cm)
+ .build()) {
+
+ client.start();
+
+ for (final URIScheme uriScheme : URIScheme.values()) {
+ final SimpleHttpRequest request = SimpleRequestBuilder.get()
+ .setHttpHost(new HttpHost(uriScheme.id, "httpbin.org"))
+ .setPath("/headers")
+ .build();
+
+ System.out.println("Executing request " + request);
+ final Future future = client.execute(
+ SimpleRequestProducer.create(request),
+ SimpleResponseConsumer.create(),
+ new FutureCallback() {
+
+ @Override
+ public void completed(final SimpleHttpResponse response) {
+ System.out.println(request + "->" + new StatusLine(response));
+ System.out.println(response.getBody());
+ }
+
+ @Override
+ public void failed(final Exception ex) {
+ System.out.println(request + "->" + ex);
+ }
+
+ @Override
+ public void cancelled() {
+ System.out.println(request + " cancelled");
+ }
+
+ });
+ future.get();
+ }
+
+ System.out.println("Shutting down");
+ client.close(CloseMode.GRACEFUL);
+ }
+ }
+
+}
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientConfiguration.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientConfiguration.java
index 42d827e3b..5c900af69 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientConfiguration.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientConfiguration.java
@@ -44,6 +44,7 @@ import org.apache.hc.client5.http.auth.StandardAuthScheme;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.config.ConnectionConfig;
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.CookieStore;
import org.apache.hc.client5.http.cookie.StandardCookieSpec;
@@ -80,6 +81,7 @@ import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.message.BasicHeader;
import org.apache.hc.core5.http.message.BasicLineParser;
import org.apache.hc.core5.http.message.LineParser;
+import org.apache.hc.core5.http.ssl.TLS;
import org.apache.hc.core5.pool.PoolConcurrencyPolicy;
import org.apache.hc.core5.pool.PoolReusePolicy;
import org.apache.hc.core5.ssl.SSLContexts;
@@ -183,6 +185,13 @@ public class ClientConfiguration {
.setConnectTimeout(Timeout.ofSeconds(30))
.setSocketTimeout(Timeout.ofSeconds(30))
.setValidateAfterInactivity(TimeValue.ofSeconds(10))
+ .setTimeToLive(TimeValue.ofHours(1))
+ .build());
+
+ // Use TLS v1.3 only
+ connManager.setDefaultTlsConfig(TlsConfig.custom()
+ .setHandshakeTimeout(Timeout.ofSeconds(30))
+ .setSupportedProtocols(TLS.V_1_3)
.build());
// Configure total max or per route limits for persistent connections
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientConnectionConfig.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientConnectionConfig.java
new file mode 100644
index 000000000..bcbd2097b
--- /dev/null
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientConnectionConfig.java
@@ -0,0 +1,103 @@
+/*
+ * ====================================================================
+ * 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.examples;
+
+import org.apache.hc.client5.http.config.ConnectionConfig;
+import org.apache.hc.client5.http.config.TlsConfig;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
+import org.apache.hc.client5.http.impl.classic.HttpClients;
+import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
+import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
+import org.apache.hc.core5.http.ClassicHttpRequest;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.URIScheme;
+import org.apache.hc.core5.http.io.entity.EntityUtils;
+import org.apache.hc.core5.http.io.support.ClassicRequestBuilder;
+import org.apache.hc.core5.http.message.StatusLine;
+import org.apache.hc.core5.http.ssl.TLS;
+import org.apache.hc.core5.util.TimeValue;
+import org.apache.hc.core5.util.Timeout;
+
+/**
+ * This example demonstrates how to use connection configuration on a per-route or a per-host
+ * basis.
+ */
+public class ClientConnectionConfig {
+
+ public final static void main(final String[] args) throws Exception {
+ final PoolingHttpClientConnectionManager cm = PoolingHttpClientConnectionManagerBuilder.create()
+ .setConnectionConfigResolver(route -> {
+ // Use different settings for all secure (TLS) connections
+ final HttpHost targetHost = route.getTargetHost();
+ if (route.isSecure()) {
+ return ConnectionConfig.custom()
+ .setConnectTimeout(Timeout.ofMinutes(2))
+ .setSocketTimeout(Timeout.ofMinutes(2))
+ .setValidateAfterInactivity(TimeValue.ofMinutes(1))
+ .setTimeToLive(TimeValue.ofHours(1))
+ .build();
+ } else {
+ return ConnectionConfig.custom()
+ .setConnectTimeout(Timeout.ofMinutes(1))
+ .setSocketTimeout(Timeout.ofMinutes(1))
+ .setValidateAfterInactivity(TimeValue.ofSeconds(15))
+ .setTimeToLive(TimeValue.ofMinutes(15))
+ .build();
+ }
+ })
+ .setTlsConfigResolver(host -> {
+ // Use different settings for specific hosts
+ if (host.getSchemeName().equalsIgnoreCase("httpbin.org")) {
+ return TlsConfig.custom()
+ .setSupportedProtocols(TLS.V_1_3)
+ .setHandshakeTimeout(Timeout.ofSeconds(10))
+ .build();
+ } else {
+ return TlsConfig.DEFAULT;
+ }
+ })
+ .build();
+ try (CloseableHttpClient httpclient = HttpClients.custom()
+ .setConnectionManager(cm)
+ .build()) {
+
+ for (final URIScheme uriScheme : URIScheme.values()) {
+ final ClassicHttpRequest request = ClassicRequestBuilder.get()
+ .setHttpHost(new HttpHost(uriScheme.id, "httpbin.org"))
+ .setPath("/headers")
+ .build();
+ System.out.println("Executing request " + request);
+ try (CloseableHttpResponse response = httpclient.execute(request)) {
+ System.out.println(request + "->" + new StatusLine(response));
+ EntityUtils.consume(response.getEntity());
+ }
+ }
+ }
+ }
+
+}
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientCustomSSL.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientCustomSSL.java
index b9c202554..88382d314 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientCustomSSL.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientCustomSSL.java
@@ -32,6 +32,7 @@ import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import org.apache.hc.client5.http.classic.methods.HttpGet;
+import org.apache.hc.client5.http.config.TlsConfig;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
@@ -43,6 +44,7 @@ import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactoryBuilder;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.ssl.TLS;
import org.apache.hc.core5.ssl.SSLContexts;
+import org.apache.hc.core5.util.Timeout;
/**
* This example demonstrates how to create secure connections with a custom SSL
@@ -58,13 +60,16 @@ public class ClientCustomSSL {
return "CN=httpbin.org".equalsIgnoreCase(cert.getSubjectDN().getName());
})
.build();
- // Allow TLSv1.2 protocol only
final SSLConnectionSocketFactory sslSocketFactory = SSLConnectionSocketFactoryBuilder.create()
.setSslContext(sslcontext)
- .setTlsVersions(TLS.V_1_2)
.build();
+ // Allow TLSv1.3 protocol only
final HttpClientConnectionManager cm = PoolingHttpClientConnectionManagerBuilder.create()
.setSSLSocketFactory(sslSocketFactory)
+ .setDefaultTlsConfig(TlsConfig.custom()
+ .setHandshakeTimeout(Timeout.ofSeconds(30))
+ .setSupportedProtocols(TLS.V_1_3)
+ .build())
.build();
try (CloseableHttpClient httpclient = HttpClients.custom()
.setConnectionManager(cm)