You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2021/10/23 17:53:17 UTC

[httpcomponents-client] 02/02: Updated connection and TLS configuration examples

This is an automated email from the ASF dual-hosted git repository.

olegk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/httpcomponents-client.git

commit ffc8cd7585f13689170bae1e1b894f649b6581a7
Author: Oleg Kalnichevski <ol...@apache.org>
AuthorDate: Sat Oct 23 19:48:00 2021 +0200

    Updated connection and TLS configuration examples
---
 .../apache/hc/client5/http/config/TlsConfig.java   |  18 +++
 .../http/examples/AsyncClientConnectionConfig.java | 133 +++++++++++++++++++++
 .../client5/http/examples/ClientConfiguration.java |   9 ++
 .../http/examples/ClientConnectionConfig.java      | 103 ++++++++++++++++
 .../hc/client5/http/examples/ClientCustomSSL.java  |   9 +-
 5 files changed, 270 insertions(+), 2 deletions(-)

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 7a014e2..45acdb9 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;
 
@@ -167,6 +168,23 @@ public class TlsConfig implements Cloneable {
         }
 
         /**
+         * Determines supported TLS protocols.
+         * <p>
+         * Default: {@code null} (undefined)
+         * </p>
+         */
+        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.
          * <p>
          * Default: {@code null} (undefined)
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 0000000..7f2dd3a
--- /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
+ * <http://www.apache.org/>.
+ *
+ */
+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<SimpleHttpResponse> future = client.execute(
+                        SimpleRequestProducer.create(request),
+                        SimpleResponseConsumer.create(),
+                        new FutureCallback<SimpleHttpResponse>() {
+
+                            @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 42d827e..5c900af 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 0000000..bcbd209
--- /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
+ * <http://www.apache.org/>.
+ *
+ */
+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 b9c2025..88382d3 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)