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/03/24 12:37:25 UTC
[httpcomponents-client] 01/01: Moved connection management related
settings from RequestConfig to new class ConnectionMgmtConfig
This is an automated email from the ASF dual-hosted git repository.
olegk pushed a commit to branch conn_mgmt_config
in repository https://gitbox.apache.org/repos/asf/httpcomponents-client.git
commit 395c70f505b516ada1d7986a32c94f58e597d7d8
Author: Oleg Kalnichevski <ol...@apache.org>
AuthorDate: Mon Mar 22 22:10:18 2021 +0100
Moved connection management related settings from RequestConfig to new class ConnectionMgmtConfig
---
.../apache/hc/client5/http/fluent/Executor.java | 11 +-
.../async/AbstractHttp1IntegrationTestBase.java | 6 +-
.../hc/client5/testing/async/TestH2Async.java | 4 +
.../client5/testing/async/TestH2AsyncRedirect.java | 4 +
.../testing/async/TestH2ClientAuthentication.java | 4 +
.../hc/client5/testing/async/TestH2Reactive.java | 4 +
.../hc/client5/testing/async/TestHttp1Async.java | 6 +-
.../testing/async/TestHttp1AsyncRedirects.java | 6 +-
.../TestHttp1AsyncStatefulConnManagement.java | 6 +-
.../async/TestHttp1ClientAuthentication.java | 6 +-
.../client5/testing/async/TestHttp1Reactive.java | 6 +-
.../external/HttpAsyncClientCompatibilityTest.java | 8 +-
.../external/HttpClientCompatibilityTest.java | 5 +-
.../client5/testing/sync/LocalServerTestBase.java | 6 +-
.../client5/http/config/ConnectionMgmtConfig.java | 202 +++++++++++++++++++++
.../hc/client5/http/config/RequestConfig.java | 23 ++-
.../http/impl/async/H2AsyncClientBuilder.java | 40 +++-
.../http/impl/async/InternalH2AsyncClient.java | 5 +-
.../impl/async/InternalH2AsyncExecRuntime.java | 9 +-
.../http/impl/async/InternalH2ConnPool.java | 130 +++++++++++++
.../http/impl/async/MinimalH2AsyncClient.java | 34 +++-
.../impl/io/BasicHttpClientConnectionManager.java | 21 ++-
.../io/PoolingHttpClientConnectionManager.java | 92 +++++++++-
.../PoolingHttpClientConnectionManagerBuilder.java | 68 ++++++-
.../nio/PoolingAsyncClientConnectionManager.java | 71 +++++++-
...PoolingAsyncClientConnectionManagerBuilder.java | 49 ++++-
.../hc/client5/http/config/TestRequestConfig.java | 6 -
.../client5/http/examples/ClientConfiguration.java | 19 +-
28 files changed, 768 insertions(+), 83 deletions(-)
diff --git a/httpclient5-fluent/src/main/java/org/apache/hc/client5/http/fluent/Executor.java b/httpclient5-fluent/src/main/java/org/apache/hc/client5/http/fluent/Executor.java
index c1d8b7d..488faf0 100644
--- a/httpclient5-fluent/src/main/java/org/apache/hc/client5/http/fluent/Executor.java
+++ b/httpclient5-fluent/src/main/java/org/apache/hc/client5/http/fluent/Executor.java
@@ -26,15 +26,13 @@
*/
package org.apache.hc.client5.http.fluent;
-import java.io.IOException;
-import java.net.URISyntaxException;
-
import org.apache.hc.client5.http.auth.AuthCache;
import org.apache.hc.client5.http.auth.AuthScope;
import org.apache.hc.client5.http.auth.Credentials;
import org.apache.hc.client5.http.auth.CredentialsStore;
import org.apache.hc.client5.http.auth.NTCredentials;
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
+import org.apache.hc.client5.http.config.ConnectionMgmtConfig;
import org.apache.hc.client5.http.cookie.CookieStore;
import org.apache.hc.client5.http.impl.auth.BasicAuthCache;
import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
@@ -46,6 +44,9 @@ import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.util.TimeValue;
+import java.io.IOException;
+import java.net.URISyntaxException;
+
/**
* Executor for {@link Request}s.
* <p>
@@ -64,7 +65,9 @@ public class Executor {
.useSystemProperties()
.setMaxConnPerRoute(100)
.setMaxConnTotal(200)
- .setValidateAfterInactivity(TimeValue.ofSeconds(10))
+ .setDefaultConnectionMgmtConfig(ConnectionMgmtConfig.custom()
+ .setValidateAfterInactivity(TimeValue.ofSeconds(10))
+ .build())
.build())
.useSystemProperties()
.evictExpiredConnections()
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttp1IntegrationTestBase.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttp1IntegrationTestBase.java
index 2a7a51d..82cb433 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttp1IntegrationTestBase.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttp1IntegrationTestBase.java
@@ -30,6 +30,7 @@ package org.apache.hc.client5.testing.async;
import java.net.InetSocketAddress;
import java.util.concurrent.Future;
+import org.apache.hc.client5.http.config.ConnectionMgmtConfig;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder;
@@ -69,6 +70,10 @@ public abstract class AbstractHttp1IntegrationTestBase extends AbstractServerTes
@Override
protected void before() throws Throwable {
connManager = PoolingAsyncClientConnectionManagerBuilder.create()
+ .setDefaultConnectionMgmtConfig(ConnectionMgmtConfig.custom()
+ .setConnectTimeout(TIMEOUT)
+ .setSocketTimeout(TIMEOUT)
+ .build())
.setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext()))
.build();
}
@@ -91,7 +96,6 @@ public abstract class AbstractHttp1IntegrationTestBase extends AbstractServerTes
clientBuilder = HttpAsyncClientBuilder.create()
.setDefaultRequestConfig(RequestConfig.custom()
.setConnectionRequestTimeout(TIMEOUT)
- .setConnectTimeout(TIMEOUT)
.build())
.setConnectionManager(connManager);
}
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2Async.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2Async.java
index 2076143..6d5f1c8 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2Async.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2Async.java
@@ -29,6 +29,7 @@ package org.apache.hc.client5.testing.async;
import java.util.Arrays;
import java.util.Collection;
+import org.apache.hc.client5.http.config.ConnectionMgmtConfig;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
import org.apache.hc.client5.http.impl.async.H2AsyncClientBuilder;
@@ -63,7 +64,10 @@ public class TestH2Async extends AbstractHttpAsyncFundamentalsTest<CloseableHttp
clientBuilder = H2AsyncClientBuilder.create()
.setDefaultRequestConfig(RequestConfig.custom()
.setConnectionRequestTimeout(TIMEOUT)
+ .build())
+ .setDefaultConnectionMgmtConfig(ConnectionMgmtConfig.custom()
.setConnectTimeout(TIMEOUT)
+ .setSocketTimeout(TIMEOUT)
.build())
.setTlsStrategy(new BasicClientTlsStrategy(SSLTestContexts.createClientSSLContext()));
}
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2AsyncRedirect.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2AsyncRedirect.java
index ed23143..a9c5629 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2AsyncRedirect.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2AsyncRedirect.java
@@ -29,6 +29,7 @@ package org.apache.hc.client5.testing.async;
import java.util.Arrays;
import java.util.Collection;
+import org.apache.hc.client5.http.config.ConnectionMgmtConfig;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
import org.apache.hc.client5.http.impl.async.H2AsyncClientBuilder;
@@ -66,7 +67,10 @@ public class TestH2AsyncRedirect extends AbstractHttpAsyncRedirectsTest<Closeabl
clientBuilder = H2AsyncClientBuilder.create()
.setDefaultRequestConfig(RequestConfig.custom()
.setConnectionRequestTimeout(TIMEOUT)
+ .build())
+ .setDefaultConnectionMgmtConfig(ConnectionMgmtConfig.custom()
.setConnectTimeout(TIMEOUT)
+ .setSocketTimeout(TIMEOUT)
.build())
.setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext()));
}
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2ClientAuthentication.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2ClientAuthentication.java
index fa3a01b..60b220a 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2ClientAuthentication.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2ClientAuthentication.java
@@ -31,6 +31,7 @@ import java.util.Collection;
import org.apache.hc.client5.http.AuthenticationStrategy;
import org.apache.hc.client5.http.auth.AuthSchemeFactory;
+import org.apache.hc.client5.http.config.ConnectionMgmtConfig;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
import org.apache.hc.client5.http.impl.async.H2AsyncClientBuilder;
@@ -67,7 +68,10 @@ public class TestH2ClientAuthentication extends AbstractHttpAsyncClientAuthentic
clientBuilder = H2AsyncClientBuilder.create()
.setDefaultRequestConfig(RequestConfig.custom()
.setConnectionRequestTimeout(TIMEOUT)
+ .build())
+ .setDefaultConnectionMgmtConfig(ConnectionMgmtConfig.custom()
.setConnectTimeout(TIMEOUT)
+ .setSocketTimeout(TIMEOUT)
.build())
.setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext()));
}
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2Reactive.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2Reactive.java
index 76bd0df..35ba046 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2Reactive.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestH2Reactive.java
@@ -29,6 +29,7 @@ package org.apache.hc.client5.testing.async;
import java.util.Arrays;
import java.util.Collection;
+import org.apache.hc.client5.http.config.ConnectionMgmtConfig;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
import org.apache.hc.client5.http.impl.async.H2AsyncClientBuilder;
@@ -63,7 +64,10 @@ public class TestH2Reactive extends AbstractHttpReactiveFundamentalsTest<Closeab
clientBuilder = H2AsyncClientBuilder.create()
.setDefaultRequestConfig(RequestConfig.custom()
.setConnectionRequestTimeout(TIMEOUT)
+ .build())
+ .setDefaultConnectionMgmtConfig(ConnectionMgmtConfig.custom()
.setConnectTimeout(TIMEOUT)
+ .setSocketTimeout(TIMEOUT)
.build())
.setTlsStrategy(new BasicClientTlsStrategy(SSLTestContexts.createClientSSLContext()));
}
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1Async.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1Async.java
index cfa3749..76a3ca9 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1Async.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1Async.java
@@ -33,6 +33,7 @@ import java.util.concurrent.Future;
import org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
import org.apache.hc.client5.http.async.methods.SimpleHttpRequests;
import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
+import org.apache.hc.client5.http.config.ConnectionMgmtConfig;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder;
@@ -75,6 +76,10 @@ public class TestHttp1Async extends AbstractHttpAsyncFundamentalsTest<CloseableH
protected void before() throws Throwable {
connManager = PoolingAsyncClientConnectionManagerBuilder.create()
.setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext()))
+ .setDefaultConnectionMgmtConfig(ConnectionMgmtConfig.custom()
+ .setConnectTimeout(TIMEOUT)
+ .setSocketTimeout(TIMEOUT)
+ .build())
.build();
}
@@ -96,7 +101,6 @@ public class TestHttp1Async extends AbstractHttpAsyncFundamentalsTest<CloseableH
clientBuilder = HttpAsyncClientBuilder.create()
.setDefaultRequestConfig(RequestConfig.custom()
.setConnectionRequestTimeout(TIMEOUT)
- .setConnectTimeout(TIMEOUT)
.build())
.setConnectionManager(connManager);
}
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1AsyncRedirects.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1AsyncRedirects.java
index b02e55d..06e9054 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1AsyncRedirects.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1AsyncRedirects.java
@@ -34,6 +34,7 @@ import java.util.concurrent.Future;
import org.apache.hc.client5.http.async.methods.SimpleHttpRequests;
import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
+import org.apache.hc.client5.http.config.ConnectionMgmtConfig;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder;
@@ -88,6 +89,10 @@ public class TestHttp1AsyncRedirects extends AbstractHttpAsyncRedirectsTest<Clos
protected void before() throws Throwable {
connManager = PoolingAsyncClientConnectionManagerBuilder.create()
.setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext()))
+ .setDefaultConnectionMgmtConfig(ConnectionMgmtConfig.custom()
+ .setConnectTimeout(TIMEOUT)
+ .setSocketTimeout(TIMEOUT)
+ .build())
.build();
}
@@ -109,7 +114,6 @@ public class TestHttp1AsyncRedirects extends AbstractHttpAsyncRedirectsTest<Clos
clientBuilder = HttpAsyncClientBuilder.create()
.setDefaultRequestConfig(RequestConfig.custom()
.setConnectionRequestTimeout(TIMEOUT)
- .setConnectTimeout(TIMEOUT)
.build())
.setConnectionManager(connManager);
}
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1AsyncStatefulConnManagement.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1AsyncStatefulConnManagement.java
index ce79333..9945abd 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1AsyncStatefulConnManagement.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1AsyncStatefulConnManagement.java
@@ -32,6 +32,7 @@ import org.apache.hc.client5.http.UserTokenHandler;
import org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
import org.apache.hc.client5.http.async.methods.SimpleHttpRequests;
import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
+import org.apache.hc.client5.http.config.ConnectionMgmtConfig;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder;
@@ -67,6 +68,10 @@ public class TestHttp1AsyncStatefulConnManagement extends AbstractIntegrationTes
protected void before() throws Throwable {
connManager = PoolingAsyncClientConnectionManagerBuilder.create()
.setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext()))
+ .setDefaultConnectionMgmtConfig(ConnectionMgmtConfig.custom()
+ .setConnectTimeout(TIMEOUT)
+ .setSocketTimeout(TIMEOUT)
+ .build())
.build();
}
@@ -87,7 +92,6 @@ public class TestHttp1AsyncStatefulConnManagement extends AbstractIntegrationTes
protected void before() throws Throwable {
clientBuilder = HttpAsyncClientBuilder.create()
.setDefaultRequestConfig(RequestConfig.custom()
- .setConnectTimeout(TIMEOUT)
.setConnectionRequestTimeout(TIMEOUT)
.build())
.setConnectionManager(connManager);
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1ClientAuthentication.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1ClientAuthentication.java
index c90b5f8..b288464 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1ClientAuthentication.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1ClientAuthentication.java
@@ -36,6 +36,7 @@ import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
import org.apache.hc.client5.http.auth.AuthSchemeFactory;
import org.apache.hc.client5.http.auth.AuthScope;
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
+import org.apache.hc.client5.http.config.ConnectionMgmtConfig;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder;
@@ -83,6 +84,10 @@ public class TestHttp1ClientAuthentication extends AbstractHttpAsyncClientAuthen
protected void before() throws Throwable {
connManager = PoolingAsyncClientConnectionManagerBuilder.create()
.setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext()))
+ .setDefaultConnectionMgmtConfig(ConnectionMgmtConfig.custom()
+ .setConnectTimeout(TIMEOUT)
+ .setSocketTimeout(TIMEOUT)
+ .build())
.build();
}
@@ -104,7 +109,6 @@ public class TestHttp1ClientAuthentication extends AbstractHttpAsyncClientAuthen
clientBuilder = HttpAsyncClientBuilder.create()
.setDefaultRequestConfig(RequestConfig.custom()
.setConnectionRequestTimeout(TIMEOUT)
- .setConnectTimeout(TIMEOUT)
.build())
.setConnectionManager(connManager);
}
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1Reactive.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1Reactive.java
index efb74a1..802849c 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1Reactive.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1Reactive.java
@@ -32,6 +32,7 @@ import java.util.Collection;
import org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
import org.apache.hc.client5.http.async.methods.SimpleHttpRequests;
+import org.apache.hc.client5.http.config.ConnectionMgmtConfig;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder;
@@ -80,6 +81,10 @@ public class TestHttp1Reactive extends AbstractHttpReactiveFundamentalsTest<Clos
protected void before() throws Throwable {
connManager = PoolingAsyncClientConnectionManagerBuilder.create()
.setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext()))
+ .setDefaultConnectionMgmtConfig(ConnectionMgmtConfig.custom()
+ .setConnectTimeout(TIMEOUT)
+ .setSocketTimeout(TIMEOUT)
+ .build())
.build();
}
@@ -101,7 +106,6 @@ public class TestHttp1Reactive extends AbstractHttpReactiveFundamentalsTest<Clos
clientBuilder = HttpAsyncClientBuilder.create()
.setDefaultRequestConfig(RequestConfig.custom()
.setConnectionRequestTimeout(TIMEOUT)
- .setConnectTimeout(TIMEOUT)
.build())
.setConnectionManager(connManager);
}
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 607e17b..230c673 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
@@ -117,9 +117,6 @@ public class HttpAsyncClientCompatibilityTest {
this.target = target;
this.proxy = proxy;
this.credentialsProvider = new BasicCredentialsProvider();
- final RequestConfig requestConfig = RequestConfig.custom()
- .setProxy(proxy)
- .build();
if (proxy != null && proxyCreds != null) {
this.credentialsProvider.setCredentials(new AuthScope(proxy), proxyCreds);
}
@@ -129,10 +126,9 @@ public class HttpAsyncClientCompatibilityTest {
.setTlsStrategy(new DefaultClientTlsStrategy(sslContext))
.build();
this.client = HttpAsyncClients.custom()
- .setVersionPolicy(this.versionPolicy)
+ .setVersionPolicy(versionPolicy)
.setConnectionManager(this.connManager)
- .setProxy(this.proxy)
- .setDefaultRequestConfig(requestConfig)
+ .setProxy(proxy)
.build();
}
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/HttpClientCompatibilityTest.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/HttpClientCompatibilityTest.java
index 5be2651..713a1d0 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/HttpClientCompatibilityTest.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/external/HttpClientCompatibilityTest.java
@@ -95,9 +95,6 @@ public class HttpClientCompatibilityTest {
this.target = target;
this.proxy = proxy;
this.credentialsProvider = new BasicCredentialsProvider();
- final RequestConfig requestConfig = RequestConfig.custom()
- .setProxy(proxy)
- .build();
if (proxy != null && proxyCreds != null) {
this.credentialsProvider.setCredentials(new AuthScope(proxy), proxyCreds);
}
@@ -108,7 +105,7 @@ public class HttpClientCompatibilityTest {
.build();
this.client = HttpClients.custom()
.setConnectionManager(this.connManager)
- .setDefaultRequestConfig(requestConfig)
+ .setProxy(proxy)
.build();
}
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/LocalServerTestBase.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/LocalServerTestBase.java
index 07a98b5..c4e3bbe 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/LocalServerTestBase.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/LocalServerTestBase.java
@@ -29,6 +29,7 @@ package org.apache.hc.client5.testing.sync;
import java.io.IOException;
+import org.apache.hc.client5.http.config.ConnectionMgmtConfig;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
@@ -110,10 +111,13 @@ public abstract class LocalServerTestBase {
connManager.setDefaultSocketConfig(SocketConfig.custom()
.setSoTimeout(TIMEOUT)
.build());
+ connManager.setDefaultConnectionMgmtConfig(ConnectionMgmtConfig.custom()
+ .setConnectTimeout(TIMEOUT)
+ .build());
+
clientBuilder = HttpClientBuilder.create()
.setDefaultRequestConfig(RequestConfig.custom()
.setConnectionRequestTimeout(TIMEOUT)
- .setConnectTimeout(TIMEOUT)
.build())
.setConnectionManager(connManager);
}
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/config/ConnectionMgmtConfig.java b/httpclient5/src/main/java/org/apache/hc/client5/http/config/ConnectionMgmtConfig.java
new file mode 100644
index 0000000..7076e5d
--- /dev/null
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/config/ConnectionMgmtConfig.java
@@ -0,0 +1,202 @@
+/*
+ * ====================================================================
+ * 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.config;
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.util.TimeValue;
+import org.apache.hc.core5.util.Timeout;
+
+/**
+ * Immutable class encapsulating connection initialization and management settings.
+ *
+ * @since 5.2
+ */
+@Contract(threading = ThreadingBehavior.IMMUTABLE)
+public class ConnectionMgmtConfig implements Cloneable {
+
+ private static final Timeout DEFAULT_CONNECT_TIMEOUT = Timeout.ofMinutes(3);
+
+ public static final ConnectionMgmtConfig DEFAULT = new Builder().build();
+
+ private final Timeout socketTimeout;
+ private final Timeout connectTimeout;
+ private final TimeValue validateAfterInactivity;
+
+ /**
+ * Intended for CDI compatibility
+ */
+ protected ConnectionMgmtConfig() {
+ this(DEFAULT_CONNECT_TIMEOUT, null, null);
+ }
+
+ ConnectionMgmtConfig(
+ final Timeout connectTimeout,
+ final Timeout socketTimeout,
+ final TimeValue validateAfterInactivity) {
+ super();
+ this.connectTimeout = connectTimeout;
+ this.socketTimeout = socketTimeout;
+ this.validateAfterInactivity = validateAfterInactivity;
+ }
+
+ /**
+ * @see Builder#setSocketTimeout(Timeout)
+ */
+ public Timeout getSocketTimeout() {
+ return socketTimeout;
+ }
+
+ /**
+ * @see Builder#setConnectTimeout(Timeout)
+ */
+ public Timeout getConnectTimeout() {
+ return connectTimeout;
+ }
+
+ /**
+ * @see Builder#setValidateAfterInactivity(TimeValue)
+ */
+ public TimeValue getValidateAfterInactivity() {
+ return validateAfterInactivity;
+ }
+
+ @Override
+ protected ConnectionMgmtConfig clone() throws CloneNotSupportedException {
+ return (ConnectionMgmtConfig) super.clone();
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("[");
+ builder.append(", connectTimeout=").append(connectTimeout);
+ builder.append(", socketTimeout=").append(socketTimeout);
+ builder.append(", validateAfterInactivity=").append(validateAfterInactivity);
+ builder.append("]");
+ return builder.toString();
+ }
+
+ public static ConnectionMgmtConfig.Builder custom() {
+ return new Builder();
+ }
+
+ public static ConnectionMgmtConfig.Builder copy(final ConnectionMgmtConfig config) {
+ return new Builder()
+ .setConnectTimeout(config.getConnectTimeout())
+ .setSocketTimeout(config.getSocketTimeout())
+ .setValidateAfterInactivity(config.getValidateAfterInactivity());
+ }
+
+ public static class Builder {
+
+ private Timeout socketTimeout;
+ private Timeout connectTimeout;
+ private TimeValue validateAfterInactivity;
+
+ Builder() {
+ super();
+ this.connectTimeout = DEFAULT_CONNECT_TIMEOUT;
+ }
+
+
+ /**
+ * @see #setSocketTimeout(Timeout)
+ */
+ public Builder setSocketTimeout(final int soTimeout, final TimeUnit timeUnit) {
+ this.socketTimeout = Timeout.of(soTimeout, timeUnit);
+ return this;
+ }
+
+ /**
+ * Determines the default socket timeout value for I/O operations.
+ * <p>
+ * Default: 3 minutes
+ * </p>
+ *
+ * @return the default socket timeout value for I/O operations.
+ */
+ public Builder setSocketTimeout(final Timeout soTimeout) {
+ this.socketTimeout = soTimeout;
+ return this;
+ }
+
+ /**
+ * 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).
+ * <p>
+ * A timeout value of zero is interpreted as an infinite timeout.
+ * </p>
+ * <p>
+ * Default: 3 minutes
+ * </p>
+ */
+ public Builder setConnectTimeout(final Timeout connectTimeout) {
+ this.connectTimeout = connectTimeout;
+ return this;
+ }
+
+ /**
+ * @see #setConnectTimeout(Timeout)
+ */
+ public Builder setConnectTimeout(final long connectTimeout, final TimeUnit timeUnit) {
+ this.connectTimeout = Timeout.of(connectTimeout, timeUnit);
+ return this;
+ }
+
+ /**
+ * Defines period of inactivity after which persistent connections must
+ * be re-validated prior to being leased to the consumer. Negative values passed
+ * to this method disable connection validation.
+ */
+ public Builder setValidateAfterInactivity(final TimeValue validateAfterInactivity) {
+ this.validateAfterInactivity = validateAfterInactivity;
+ return this;
+ }
+
+ /**
+ * @see #setValidateAfterInactivity(TimeValue)
+ */
+ public Builder setValidateAfterInactivity(final long validateAfterInactivity, final TimeUnit timeUnit) {
+ this.validateAfterInactivity = TimeValue.of(validateAfterInactivity, timeUnit);
+ return this;
+ }
+
+ public ConnectionMgmtConfig build() {
+ return new ConnectionMgmtConfig(
+ connectTimeout != null ? connectTimeout : DEFAULT_CONNECT_TIMEOUT,
+ socketTimeout,
+ validateAfterInactivity);
+ }
+
+ }
+
+}
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/config/RequestConfig.java b/httpclient5/src/main/java/org/apache/hc/client5/http/config/RequestConfig.java
index 9bcf749..45a062a 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/config/RequestConfig.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/config/RequestConfig.java
@@ -43,7 +43,6 @@ import org.apache.hc.core5.util.Timeout;
public class RequestConfig implements Cloneable {
private static final Timeout DEFAULT_CONNECTION_REQUEST_TIMEOUT = Timeout.ofMinutes(3);
- private static final Timeout DEFAULT_CONNECT_TIMEOUT = Timeout.ofMinutes(3);
private static final TimeValue DEFAULT_CONN_KEEP_ALIVE = TimeValue.ofMinutes(3);
public static final RequestConfig DEFAULT = new Builder().build();
@@ -69,7 +68,7 @@ public class RequestConfig implements Cloneable {
*/
protected RequestConfig() {
this(false, null, null, false, false, 0, false, null, null,
- DEFAULT_CONNECTION_REQUEST_TIMEOUT, DEFAULT_CONNECT_TIMEOUT, null, DEFAULT_CONN_KEEP_ALIVE, false, false);
+ DEFAULT_CONNECTION_REQUEST_TIMEOUT, null, null, DEFAULT_CONN_KEEP_ALIVE, false, false);
}
RequestConfig(
@@ -115,7 +114,11 @@ public class RequestConfig implements Cloneable {
/**
* @see Builder#setProxy(HttpHost)
+ *
+ * @deprecated Use {@link org.apache.hc.client5.http.impl.routing.DefaultProxyRoutePlanner}
+ * or a custom {@link org.apache.hc.client5.http.routing.HttpRoutePlanner}.
*/
+ @Deprecated
public HttpHost getProxy() {
return proxy;
}
@@ -178,7 +181,10 @@ public class RequestConfig implements Cloneable {
/**
* @see Builder#setConnectTimeout(Timeout)
+ *
+ * @deprecated Use {@link ConnectionMgmtConfig#getConnectTimeout()}.
*/
+ @Deprecated
public Timeout getConnectTimeout() {
return connectTimeout;
}
@@ -286,7 +292,6 @@ public class RequestConfig implements Cloneable {
this.maxRedirects = 50;
this.authenticationEnabled = true;
this.connectionRequestTimeout = DEFAULT_CONNECTION_REQUEST_TIMEOUT;
- this.connectTimeout = DEFAULT_CONNECT_TIMEOUT;
this.contentCompressionEnabled = true;
this.hardCancellationEnabled = true;
}
@@ -323,7 +328,11 @@ public class RequestConfig implements Cloneable {
* <p>
* Default: {@code null}
* </p>
+ *
+ * @deprecated Use {@link org.apache.hc.client5.http.impl.routing.DefaultProxyRoutePlanner}
+ * or a custom {@link org.apache.hc.client5.http.routing.HttpRoutePlanner}.
*/
+ @Deprecated
public Builder setProxy(final HttpHost proxy) {
this.proxy = proxy;
return this;
@@ -444,7 +453,10 @@ public class RequestConfig implements Cloneable {
* <p>
* Default: 3 minutes
* </p>
+ *
+ * @deprecated Use {@link ConnectionMgmtConfig.Builder#setConnectTimeout(Timeout)}.
*/
+ @Deprecated
public Builder setConnectTimeout(final Timeout connectTimeout) {
this.connectTimeout = connectTimeout;
return this;
@@ -452,7 +464,10 @@ public class RequestConfig implements Cloneable {
/**
* @see #setConnectTimeout(Timeout)
+ *
+ * @deprecated Use {@link ConnectionMgmtConfig.Builder#setConnectTimeout(long, TimeUnit)}.
*/
+ @Deprecated
public Builder setConnectTimeout(final long connectTimeout, final TimeUnit timeUnit) {
this.connectTimeout = Timeout.of(connectTimeout, timeUnit);
return this;
@@ -570,7 +585,7 @@ public class RequestConfig implements Cloneable {
targetPreferredAuthSchemes,
proxyPreferredAuthSchemes,
connectionRequestTimeout != null ? connectionRequestTimeout : DEFAULT_CONNECTION_REQUEST_TIMEOUT,
- connectTimeout != null ? connectTimeout : DEFAULT_CONNECT_TIMEOUT,
+ connectTimeout,
responseTimeout,
connectionKeepAlive != null ? connectionKeepAlive : DEFAULT_CONN_KEEP_ALIVE,
contentCompressionEnabled,
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/H2AsyncClientBuilder.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/H2AsyncClientBuilder.java
index a61a687..4195276 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/H2AsyncClientBuilder.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/H2AsyncClientBuilder.java
@@ -33,8 +33,10 @@ import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.ThreadFactory;
import org.apache.hc.client5.http.AuthenticationStrategy;
@@ -45,6 +47,7 @@ import org.apache.hc.client5.http.async.AsyncExecChainHandler;
import org.apache.hc.client5.http.auth.AuthSchemeFactory;
import org.apache.hc.client5.http.auth.CredentialsProvider;
import org.apache.hc.client5.http.auth.StandardAuthScheme;
+import org.apache.hc.client5.http.config.ConnectionMgmtConfig;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.cookie.BasicCookieStore;
import org.apache.hc.client5.http.cookie.CookieSpecFactory;
@@ -75,6 +78,7 @@ import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy;
import org.apache.hc.core5.annotation.Internal;
import org.apache.hc.core5.concurrent.DefaultThreadFactory;
import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpRequestInterceptor;
import org.apache.hc.core5.http.HttpResponseInterceptor;
import org.apache.hc.core5.http.config.CharCodingConfig;
@@ -89,7 +93,6 @@ import org.apache.hc.core5.http.protocol.HttpProcessorBuilder;
import org.apache.hc.core5.http.protocol.RequestTargetHost;
import org.apache.hc.core5.http.protocol.RequestUserAgent;
import org.apache.hc.core5.http2.config.H2Config;
-import org.apache.hc.core5.http2.nio.pool.H2ConnPool;
import org.apache.hc.core5.http2.protocol.H2RequestConnControl;
import org.apache.hc.core5.http2.protocol.H2RequestContent;
import org.apache.hc.core5.http2.protocol.H2RequestTargetHost;
@@ -189,6 +192,8 @@ public class H2AsyncClientBuilder {
private String userAgent;
private Collection<? extends Header> defaultHeaders;
private RequestConfig defaultRequestConfig;
+ private ConnectionMgmtConfig defaultConnectionMgmtConfig;
+ private Map<HttpHost, ConnectionMgmtConfig> connectionMgmtConfigMap;
private boolean evictIdleConnections;
private TimeValue maxIdleTime;
@@ -501,6 +506,29 @@ public class H2AsyncClientBuilder {
}
/**
+ * Assigns default {@link ConnectionMgmtConfig}.
+ *
+ * @since 5.2
+ */
+ public final H2AsyncClientBuilder setDefaultConnectionMgmtConfig(
+ final ConnectionMgmtConfig defaultConnectionMgmtConfig) {
+ this.defaultConnectionMgmtConfig = defaultConnectionMgmtConfig;
+ return this;
+ }
+
+ /**
+ * @since 5.2
+ */
+ public final H2AsyncClientBuilder setConnectionMgmtConfig(final HttpHost httpHost,
+ final ConnectionMgmtConfig connectionMgmtConfig) {
+ if (connectionMgmtConfigMap == null) {
+ connectionMgmtConfigMap = new HashMap<>();
+ }
+ connectionMgmtConfigMap.put(httpHost, connectionMgmtConfig);
+ return this;
+ }
+
+ /**
* Use system properties when creating and configuring default
* implementations.
*/
@@ -784,7 +812,13 @@ public class H2AsyncClientBuilder {
}
final MultihomeConnectionInitiator connectionInitiator = new MultihomeConnectionInitiator(ioReactor, dnsResolver);
- final H2ConnPool connPool = new H2ConnPool(connectionInitiator, host -> null, tlsStrategyCopy);
+ final InternalH2ConnPool connPool = new InternalH2ConnPool(connectionInitiator, host -> null, tlsStrategyCopy);
+ if (defaultConnectionMgmtConfig != null) {
+ connPool.setDefaultConnectionMgmtConfig(defaultConnectionMgmtConfig);
+ }
+ if (connectionMgmtConfigMap != null) {
+ connectionMgmtConfigMap.forEach(connPool::setConnectionMgmtConfig);
+ }
List<Closeable> closeablesCopy = closeables != null ? new ArrayList<>(closeables) : null;
if (closeablesCopy == null) {
@@ -821,7 +855,7 @@ public class H2AsyncClientBuilder {
private final Thread thread;
- public IdleConnectionEvictor(final H2ConnPool connPool, final TimeValue maxIdleTime) {
+ public IdleConnectionEvictor(final InternalH2ConnPool connPool, final TimeValue maxIdleTime) {
this.thread = new DefaultThreadFactory("idle-connection-evictor", true).newThread(() -> {
try {
while (!Thread.currentThread().isInterrupted()) {
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalH2AsyncClient.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalH2AsyncClient.java
index 6ebaf66..cb758f6 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalH2AsyncClient.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalH2AsyncClient.java
@@ -47,7 +47,6 @@ import org.apache.hc.core5.http.HttpHost;
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.nio.pool.H2ConnPool;
import org.apache.hc.core5.reactor.DefaultConnectingIOReactor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -68,14 +67,14 @@ public final class InternalH2AsyncClient extends InternalAbstractHttpAsyncClient
private static final Logger LOG = LoggerFactory.getLogger(InternalH2AsyncClient.class);
private final HttpRoutePlanner routePlanner;
- private final H2ConnPool connPool;
+ private final InternalH2ConnPool connPool;
InternalH2AsyncClient(
final DefaultConnectingIOReactor ioReactor,
final AsyncExecChainElement execChain,
final AsyncPushConsumerRegistry pushConsumerRegistry,
final ThreadFactory threadFactory,
- final H2ConnPool connPool,
+ final InternalH2ConnPool connPool,
final HttpRoutePlanner routePlanner,
final Lookup<CookieSpecFactory> cookieSpecRegistry,
final Lookup<AuthSchemeFactory> authSchemeRegistry,
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalH2AsyncExecRuntime.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalH2AsyncExecRuntime.java
index 957eeac..84411e2 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalH2AsyncExecRuntime.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalH2AsyncExecRuntime.java
@@ -44,7 +44,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.http.nio.command.RequestExecutionCommand;
-import org.apache.hc.core5.http2.nio.pool.H2ConnPool;
import org.apache.hc.core5.io.CloseMode;
import org.apache.hc.core5.reactor.Command;
import org.apache.hc.core5.reactor.IOSession;
@@ -56,14 +55,14 @@ import org.slf4j.Logger;
class InternalH2AsyncExecRuntime implements AsyncExecRuntime {
private final Logger log;
- private final H2ConnPool connPool;
+ private final InternalH2ConnPool connPool;
private final HandlerFactory<AsyncPushConsumer> pushHandlerFactory;
private final AtomicReference<Endpoint> sessionRef;
private volatile boolean reusable;
InternalH2AsyncExecRuntime(
final Logger log,
- final H2ConnPool connPool,
+ final InternalH2ConnPool connPool,
final HandlerFactory<AsyncPushConsumer> pushHandlerFactory) {
super();
this.log = log;
@@ -91,9 +90,7 @@ class InternalH2AsyncExecRuntime implements AsyncExecRuntime {
if (log.isDebugEnabled()) {
log.debug("{} acquiring endpoint ({})", id, connectTimeout);
}
- return Operations.cancellable(connPool.getSession(
- target,
- connectTimeout,
+ return Operations.cancellable(connPool.getSession(target, connectTimeout,
new FutureCallback<IOSession>() {
@Override
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalH2ConnPool.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalH2ConnPool.java
new file mode 100644
index 0000000..6baeba2
--- /dev/null
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalH2ConnPool.java
@@ -0,0 +1,130 @@
+/*
+ * ====================================================================
+ * 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.impl.async;
+
+import org.apache.hc.client5.http.config.ConnectionMgmtConfig;
+import org.apache.hc.core5.concurrent.CallbackContribution;
+import org.apache.hc.core5.concurrent.FutureCallback;
+import org.apache.hc.core5.function.Resolver;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
+import org.apache.hc.core5.http2.nio.command.PingCommand;
+import org.apache.hc.core5.http2.nio.pool.H2ConnPool;
+import org.apache.hc.core5.http2.nio.support.BasicPingHandler;
+import org.apache.hc.core5.io.CloseMode;
+import org.apache.hc.core5.io.ModalCloseable;
+import org.apache.hc.core5.reactor.Command;
+import org.apache.hc.core5.reactor.ConnectionInitiator;
+import org.apache.hc.core5.reactor.IOSession;
+import org.apache.hc.core5.util.TimeValue;
+import org.apache.hc.core5.util.Timeout;
+
+import java.net.InetSocketAddress;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.Future;
+
+class InternalH2ConnPool implements ModalCloseable {
+
+ private final H2ConnPool connPool;
+ private final ConcurrentMap<HttpHost, ConnectionMgmtConfig> connectionMgmtConfigMap;
+
+ private volatile ConnectionMgmtConfig defaultConnectionMgmtConfig;
+
+ InternalH2ConnPool(final ConnectionInitiator connectionInitiator,
+ final Resolver<HttpHost, InetSocketAddress> addressResolver,
+ final TlsStrategy tlsStrategy) {
+ this.connPool = new H2ConnPool(connectionInitiator, addressResolver, tlsStrategy);
+ this.connectionMgmtConfigMap = new ConcurrentHashMap<>();
+ }
+
+ public void close(final CloseMode closeMode) {
+ connPool.close(closeMode);
+ }
+
+ public void close() {
+ connPool.close();
+ }
+
+ public Future<IOSession> getSession(
+ final HttpHost endpoint,
+ final Timeout connectTimeout,
+ final FutureCallback<IOSession> callback) {
+ final ConnectionMgmtConfig connMgmtConfig = connectionMgmtConfigMap.getOrDefault(endpoint,
+ defaultConnectionMgmtConfig != null ? defaultConnectionMgmtConfig : ConnectionMgmtConfig.DEFAULT);
+ return connPool.getSession(
+ endpoint,
+ connectTimeout != null ? connectTimeout : connMgmtConfig.getConnectTimeout(),
+ new CallbackContribution<IOSession>(callback) {
+
+ @Override
+ public void completed(final IOSession ioSession) {
+ final Timeout socketTimeout = connMgmtConfig.getSocketTimeout();
+ if (socketTimeout != null) {
+ ioSession.setSocketTimeout(socketTimeout);
+ }
+ final TimeValue timeValue = connMgmtConfig.getValidateAfterInactivity();
+ if (TimeValue.isNonNegative(timeValue)) {
+ final long lastAccessTime = Math.min(ioSession.getLastReadTime(), ioSession.getLastWriteTime());
+ final long deadline = lastAccessTime + timeValue.toMilliseconds();
+ if (deadline <= System.currentTimeMillis()) {
+ final Timeout socketTimeoutMillis = ioSession.getSocketTimeout();
+ ioSession.enqueue(new PingCommand(new BasicPingHandler(result -> {
+ ioSession.setSocketTimeout(socketTimeoutMillis);
+ callback.completed(ioSession);
+ })), Command.Priority.NORMAL);
+ return;
+ }
+ }
+
+ callback.completed(ioSession);
+ }
+
+ });
+ }
+
+ public void closeIdle(final TimeValue idleTime) {
+ connPool.closeIdle(idleTime);
+ }
+
+ public ConnectionMgmtConfig getDefaultConnectionMgmtConfig() {
+ return defaultConnectionMgmtConfig;
+ }
+
+ public void setDefaultConnectionMgmtConfig(final ConnectionMgmtConfig defaultConnectionMgmtConfig) {
+ this.defaultConnectionMgmtConfig = defaultConnectionMgmtConfig;
+ }
+
+ public void setConnectionMgmtConfig(final HttpHost httpHost, final ConnectionMgmtConfig connectionMgmtConfig) {
+ connectionMgmtConfigMap.put(httpHost, connectionMgmtConfig);
+ }
+
+ public ConnectionMgmtConfig getConnectionMgmtConfig(final HttpHost httpHost) {
+ return connectionMgmtConfigMap.get(httpHost);
+ }
+
+}
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/MinimalH2AsyncClient.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/MinimalH2AsyncClient.java
index 6d91ff8..f13618f 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/MinimalH2AsyncClient.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/MinimalH2AsyncClient.java
@@ -35,6 +35,7 @@ import java.util.concurrent.ThreadFactory;
import org.apache.hc.client5.http.DnsResolver;
import org.apache.hc.client5.http.config.Configurable;
+import org.apache.hc.client5.http.config.ConnectionMgmtConfig;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.ConnPoolSupport;
import org.apache.hc.client5.http.impl.ExecSupport;
@@ -61,7 +62,6 @@ import org.apache.hc.core5.http.nio.command.RequestExecutionCommand;
import org.apache.hc.core5.http.nio.command.ShutdownCommand;
import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
import org.apache.hc.core5.http.protocol.HttpContext;
-import org.apache.hc.core5.http2.nio.pool.H2ConnPool;
import org.apache.hc.core5.io.CloseMode;
import org.apache.hc.core5.reactor.Command;
import org.apache.hc.core5.reactor.ConnectionInitiator;
@@ -90,7 +90,7 @@ import org.slf4j.LoggerFactory;
public final class MinimalH2AsyncClient extends AbstractMinimalHttpAsyncClientBase {
private static final Logger LOG = LoggerFactory.getLogger(MinimalH2AsyncClient.class);
- private final H2ConnPool connPool;
+ private final InternalH2ConnPool connPool;
private final ConnectionInitiator connectionInitiator;
MinimalH2AsyncClient(
@@ -112,7 +112,7 @@ public final class MinimalH2AsyncClient extends AbstractMinimalHttpAsyncClientBa
pushConsumerRegistry,
threadFactory);
this.connectionInitiator = new MultihomeConnectionInitiator(getConnectionInitiator(), dnsResolver);
- this.connPool = new H2ConnPool(this.connectionInitiator, object -> null, tlsStrategy);
+ this.connPool = new InternalH2ConnPool(this.connectionInitiator, object -> null, tlsStrategy);
}
@Override
@@ -249,4 +249,32 @@ public final class MinimalH2AsyncClient extends AbstractMinimalHttpAsyncClientBa
return cancellable;
}
+ /**
+ * @since 5.2
+ */
+ public ConnectionMgmtConfig getDefaultConnectionMgmtConfig() {
+ return connPool.getDefaultConnectionMgmtConfig();
+ }
+
+ /**
+ * @since 5.2
+ */
+ public void setDefaultConnectionMgmtConfig(final ConnectionMgmtConfig defaultConnectionMgmtConfig) {
+ connPool.setDefaultConnectionMgmtConfig(defaultConnectionMgmtConfig);
+ }
+
+ /**
+ * @since 5.2
+ */
+ public void setConnectionMgmtConfig(final HttpHost httpHost, final ConnectionMgmtConfig connectionMgmtConfig) {
+ connPool.setConnectionMgmtConfig(httpHost, connectionMgmtConfig);
+ }
+
+ /**
+ * @since 5.2
+ */
+ public ConnectionMgmtConfig getConnectionMgmtConfig(final HttpHost httpHost) {
+ return connPool.getConnectionMgmtConfig(httpHost);
+ }
+
}
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 e3ebefc..5090459 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
@@ -38,6 +38,7 @@ import java.util.concurrent.atomic.AtomicReference;
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.ConnectionMgmtConfig;
import org.apache.hc.client5.http.impl.ConnectionShutdownException;
import org.apache.hc.client5.http.io.ConnectionEndpoint;
import org.apache.hc.client5.http.io.HttpClientConnectionManager;
@@ -103,6 +104,7 @@ public class BasicHttpClientConnectionManager implements HttpClientConnectionMan
private long expiry;
private boolean leased;
private SocketConfig socketConfig;
+ private ConnectionMgmtConfig connectionMgmtConfig;
private final AtomicBoolean closed;
@@ -179,6 +181,14 @@ public class BasicHttpClientConnectionManager implements HttpClientConnectionMan
this.socketConfig = socketConfig != null ? socketConfig : SocketConfig.DEFAULT;
}
+ public synchronized ConnectionMgmtConfig getConnectionMgmtConfig() {
+ return connectionMgmtConfig;
+ }
+
+ public synchronized void setConnectionMgmtConfig(final ConnectionMgmtConfig connectionMgmtConfig) {
+ this.connectionMgmtConfig = connectionMgmtConfig != null ? connectionMgmtConfig : ConnectionMgmtConfig.DEFAULT;
+ }
+
public LeaseRequest lease(final String id, final HttpRoute route, final Object state) {
return lease(id, route, Timeout.DISABLED, state);
}
@@ -298,7 +308,7 @@ public class BasicHttpClientConnectionManager implements HttpClientConnectionMan
}
@Override
- public void connect(final ConnectionEndpoint endpoint, final TimeValue connectTimeout, final HttpContext context) throws IOException {
+ public void connect(final ConnectionEndpoint endpoint, final TimeValue timeout, final HttpContext context) throws IOException {
Args.notNull(endpoint, "Endpoint");
final InternalConnectionEndpoint internalEndpoint = cast(endpoint);
@@ -312,13 +322,20 @@ public class BasicHttpClientConnectionManager implements HttpClientConnectionMan
} else {
host = route.getTargetHost();
}
+ final ConnectionMgmtConfig config = connectionMgmtConfig != null ? connectionMgmtConfig : ConnectionMgmtConfig.DEFAULT;
+ final TimeValue connectTimeout = timeout != null ? timeout : config.getConnectTimeout();
+ final ManagedHttpClientConnection connection = internalEndpoint.getConnection();
this.connectionOperator.connect(
- internalEndpoint.getConnection(),
+ connection,
host,
route.getLocalSocketAddress(),
connectTimeout,
this.socketConfig,
context);
+ final Timeout socketTimeout = config.getSocketTimeout();
+ if (socketTimeout != null) {
+ connection.setSocketTimeout(socketTimeout);
+ }
}
@Override
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 4c8d6d4..b8183a5 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
@@ -29,6 +29,8 @@ package org.apache.hc.client5.http.impl.io;
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.CancellationException;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeoutException;
@@ -39,6 +41,7 @@ import java.util.concurrent.atomic.AtomicReference;
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.ConnectionMgmtConfig;
import org.apache.hc.client5.http.impl.ConnPoolSupport;
import org.apache.hc.client5.http.impl.ConnectionShutdownException;
import org.apache.hc.client5.http.io.ConnectionEndpoint;
@@ -113,10 +116,12 @@ public class PoolingHttpClientConnectionManager
private final HttpClientConnectionOperator connectionOperator;
private final ManagedConnPool<HttpRoute, ManagedHttpClientConnection> pool;
private final HttpConnectionFactory<ManagedHttpClientConnection> connFactory;
+ private final ConcurrentMap<HttpRoute, SocketConfig> socketConfigMap;
+ private final ConcurrentMap<HttpRoute, ConnectionMgmtConfig> connectionMgmtConfigMap;
private final AtomicBoolean closed;
private volatile SocketConfig defaultSocketConfig;
- private volatile TimeValue validateAfterInactivity;
+ private volatile ConnectionMgmtConfig defaultConnectionMgmtConfig;
public PoolingHttpClientConnectionManager() {
this(RegistryBuilder.<ConnectionSocketFactory>create()
@@ -205,6 +210,8 @@ public class PoolingHttpClientConnectionManager
throw new IllegalArgumentException("Unexpected PoolConcurrencyPolicy value: " + poolConcurrencyPolicy);
}
this.connFactory = connFactory != null ? connFactory : ManagedHttpClientConnectionFactory.INSTANCE;
+ this.socketConfigMap = new ConcurrentHashMap<>();
+ this.connectionMgmtConfigMap = new ConcurrentHashMap<>();
this.closed = new AtomicBoolean(false);
}
@@ -217,6 +224,8 @@ public class PoolingHttpClientConnectionManager
this.connectionOperator = Args.notNull(httpClientConnectionOperator, "Connection operator");
this.pool = Args.notNull(pool, "Connection pool");
this.connFactory = connFactory != null ? connFactory : ManagedHttpClientConnectionFactory.INSTANCE;
+ this.socketConfigMap = new ConcurrentHashMap<>();
+ this.connectionMgmtConfigMap = new ConcurrentHashMap<>();
this.closed = new AtomicBoolean(false);
}
@@ -282,12 +291,13 @@ public class PoolingHttpClientConnectionManager
if (LOG.isDebugEnabled()) {
LOG.debug("{} endpoint leased {}", id, ConnPoolSupport.formatStats(route, state, pool));
}
+ final ConnectionMgmtConfig connMgmtConfig = connectionMgmtConfigMap.getOrDefault(route, defaultConnectionMgmtConfig);
+ final TimeValue timeValue = connMgmtConfig != null ? connMgmtConfig.getValidateAfterInactivity() : null;
try {
- final TimeValue validateAfterInactivitySnapshot = validateAfterInactivity;
- if (TimeValue.isNonNegative(validateAfterInactivitySnapshot)) {
+ if (TimeValue.isNonNegative(timeValue)) {
final ManagedHttpClientConnection conn = poolEntry.getConnection();
if (conn != null
- && poolEntry.getUpdated() + validateAfterInactivitySnapshot.toMilliseconds() <= System.currentTimeMillis()) {
+ && poolEntry.getUpdated() + timeValue.toMilliseconds() <= System.currentTimeMillis()) {
boolean stale;
try {
stale = conn.isStale();
@@ -384,7 +394,7 @@ public class PoolingHttpClientConnectionManager
}
@Override
- public void connect(final ConnectionEndpoint endpoint, final TimeValue connectTimeout, final HttpContext context) throws IOException {
+ public void connect(final ConnectionEndpoint endpoint, final TimeValue timeout, final HttpContext context) throws IOException {
Args.notNull(endpoint, "Managed endpoint");
final InternalConnectionEndpoint internalEndpoint = cast(endpoint);
if (internalEndpoint.isConnected()) {
@@ -401,21 +411,29 @@ public class PoolingHttpClientConnectionManager
} else {
host = route.getTargetHost();
}
+ final SocketConfig socketConfig = socketConfigMap.getOrDefault(route,
+ defaultSocketConfig != null ? defaultSocketConfig : SocketConfig.DEFAULT);
+ final ConnectionMgmtConfig connMgmtConfig = connectionMgmtConfigMap.getOrDefault(route,
+ defaultConnectionMgmtConfig != null ? defaultConnectionMgmtConfig : ConnectionMgmtConfig.DEFAULT);
+ final TimeValue connectTimeout = timeout != null ? timeout : connMgmtConfig.getConnectTimeout();
if (LOG.isDebugEnabled()) {
LOG.debug("{} connecting endpoint to {} ({})", ConnPoolSupport.getId(endpoint), host, connectTimeout);
}
final ManagedHttpClientConnection conn = poolEntry.getConnection();
- final SocketConfig defaultSocketConfigSnapshot = defaultSocketConfig;
this.connectionOperator.connect(
conn,
host,
route.getLocalSocketAddress(),
- connectTimeout,
- defaultSocketConfigSnapshot != null ? defaultSocketConfigSnapshot : SocketConfig.DEFAULT,
+ timeout,
+ socketConfig != null ? socketConfig : SocketConfig.DEFAULT,
context);
if (LOG.isDebugEnabled()) {
LOG.debug("{} connected {}", ConnPoolSupport.getId(endpoint), ConnPoolSupport.getId(conn));
}
+ final Timeout socketTimeout = connMgmtConfig.getSocketTimeout();
+ if (socketTimeout != null) {
+ conn.setSocketTimeout(socketTimeout);
+ }
}
@Override
@@ -496,12 +514,57 @@ public class PoolingHttpClientConnectionManager
}
/**
+ * @since 5.2
+ */
+ public void setSocketConfig(final HttpRoute route, final SocketConfig socketConfig) {
+ socketConfigMap.put(route, defaultSocketConfig);
+ }
+
+ /**
+ * @since 5.2
+ */
+ public SocketConfig getSocketConfig(final HttpRoute route) {
+ return socketConfigMap.get(route);
+ }
+
+ /**
+ * @since 5.2
+ */
+ public ConnectionMgmtConfig getDefaultConnectionMgmtConfig() {
+ return defaultConnectionMgmtConfig;
+ }
+
+ /**
+ * @since 5.2
+ */
+ public void setDefaultConnectionMgmtConfig(final ConnectionMgmtConfig defaultConnectionMgmtConfig) {
+ this.defaultConnectionMgmtConfig = defaultConnectionMgmtConfig;
+ }
+
+ /**
+ * @since 5.2
+ */
+ public void setConnectionMgmtConfig(final HttpRoute route, final ConnectionMgmtConfig connectionMgmtConfig) {
+ connectionMgmtConfigMap.put(route, connectionMgmtConfig);
+ }
+
+ /**
+ * @since 5.2
+ */
+ public ConnectionMgmtConfig getConnectionMgmtConfig(final HttpRoute route) {
+ return connectionMgmtConfigMap.get(route);
+ }
+
+ /**
* @see #setValidateAfterInactivity(TimeValue)
*
* @since 4.4
+ *
+ * @deprecated Use {@link #getDefaultConnectionMgmtConfig()}.
*/
+ @Deprecated
public TimeValue getValidateAfterInactivity() {
- return validateAfterInactivity;
+ return defaultConnectionMgmtConfig != null ? defaultConnectionMgmtConfig.getValidateAfterInactivity() : null;
}
/**
@@ -511,9 +574,18 @@ public class PoolingHttpClientConnectionManager
* detect connections that have become stale (half-closed) while kept inactive in the pool.
*
* @since 4.4
+ *
+ * @deprecated Use {@link #setDefaultConnectionMgmtConfig(ConnectionMgmtConfig)}
*/
+ @Deprecated
public void setValidateAfterInactivity(final TimeValue validateAfterInactivity) {
- this.validateAfterInactivity = validateAfterInactivity;
+ defaultConnectionMgmtConfig = defaultConnectionMgmtConfig != null ?
+ ConnectionMgmtConfig.copy(defaultConnectionMgmtConfig)
+ .setValidateAfterInactivity(validateAfterInactivity)
+ .build() :
+ ConnectionMgmtConfig.custom()
+ .setValidateAfterInactivity(validateAfterInactivity)
+ .build();
}
private static final AtomicLong COUNT = new AtomicLong(0);
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 121127e..048f318 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
@@ -27,8 +27,13 @@
package org.apache.hc.client5.http.impl.io;
+import java.util.HashMap;
+import java.util.Map;
+
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.ConnectionMgmtConfig;
import org.apache.hc.client5.http.io.ManagedHttpClientConnection;
import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
import org.apache.hc.client5.http.socket.LayeredConnectionSocketFactory;
@@ -77,6 +82,9 @@ public class PoolingHttpClientConnectionManagerBuilder {
private PoolConcurrencyPolicy poolConcurrencyPolicy;
private PoolReusePolicy poolReusePolicy;
private SocketConfig defaultSocketConfig;
+ private Map<HttpRoute, SocketConfig> socketConfigMap;
+ private ConnectionMgmtConfig defaultConnectionMgmtConfig;
+ private Map<HttpRoute, ConnectionMgmtConfig> connectionMgmtConfigMap;
private boolean systemProperties;
@@ -84,7 +92,6 @@ public class PoolingHttpClientConnectionManagerBuilder {
private int maxConnPerRoute;
private TimeValue timeToLive;
- private TimeValue validateAfterInactivity;
public static PoolingHttpClientConnectionManagerBuilder create() {
return new PoolingHttpClientConnectionManagerBuilder();
@@ -169,6 +176,41 @@ public class PoolingHttpClientConnectionManagerBuilder {
}
/**
+ * @since 5.2
+ */
+ public final PoolingHttpClientConnectionManagerBuilder setSocketConfig(final HttpRoute route,
+ final ConnectionMgmtConfig connectionMgmtConfig) {
+ if (connectionMgmtConfigMap == null) {
+ connectionMgmtConfigMap = new HashMap<>();
+ }
+ connectionMgmtConfigMap.put(route, connectionMgmtConfig);
+ return this;
+ }
+
+ /**
+ * Assigns default {@link ConnectionMgmtConfig}.
+ *
+ * @since 5.2
+ */
+ public final PoolingHttpClientConnectionManagerBuilder setDefaultConnectionMgmtConfig(
+ final ConnectionMgmtConfig defaultConnectionMgmtConfig) {
+ this.defaultConnectionMgmtConfig = defaultConnectionMgmtConfig;
+ return this;
+ }
+
+ /**
+ * @since 5.2
+ */
+ public final PoolingHttpClientConnectionManagerBuilder setConnectionMgmtConfig(final HttpRoute route,
+ final ConnectionMgmtConfig connectionMgmtConfig) {
+ if (connectionMgmtConfigMap == null) {
+ connectionMgmtConfigMap = new HashMap<>();
+ }
+ connectionMgmtConfigMap.put(route, connectionMgmtConfig);
+ return this;
+ }
+
+ /**
* Sets maximum time to live for persistent connections
*/
public final PoolingHttpClientConnectionManagerBuilder setConnectionTimeToLive(final TimeValue timeToLive) {
@@ -180,10 +222,17 @@ public class PoolingHttpClientConnectionManagerBuilder {
* Sets period after inactivity after which persistent
* connections must be checked to ensure they are still valid.
*
- * @see org.apache.hc.core5.http.io.HttpClientConnection#isStale()
+ * @deprecated Use {@link #setDefaultConnectionMgmtConfig(ConnectionMgmtConfig)}.
*/
+ @Deprecated
public final PoolingHttpClientConnectionManagerBuilder setValidateAfterInactivity(final TimeValue validateAfterInactivity) {
- this.validateAfterInactivity = validateAfterInactivity;
+ defaultConnectionMgmtConfig = defaultConnectionMgmtConfig != null ?
+ ConnectionMgmtConfig.copy(defaultConnectionMgmtConfig)
+ .setValidateAfterInactivity(validateAfterInactivity)
+ .build() :
+ ConnectionMgmtConfig.custom()
+ .setValidateAfterInactivity(validateAfterInactivity)
+ .build();
return this;
}
@@ -197,8 +246,7 @@ public class PoolingHttpClientConnectionManagerBuilder {
}
public PoolingHttpClientConnectionManager build() {
- @SuppressWarnings("resource")
- final PoolingHttpClientConnectionManager poolingmgr = new PoolingHttpClientConnectionManager(
+ @SuppressWarnings("resource") final PoolingHttpClientConnectionManager poolingmgr = new PoolingHttpClientConnectionManager(
RegistryBuilder.<ConnectionSocketFactory>create()
.register(URIScheme.HTTP.id, PlainConnectionSocketFactory.getSocketFactory())
.register(URIScheme.HTTPS.id, sslSocketFactory != null ? sslSocketFactory :
@@ -212,10 +260,18 @@ public class PoolingHttpClientConnectionManagerBuilder {
schemePortResolver,
dnsResolver,
connectionFactory);
- poolingmgr.setValidateAfterInactivity(this.validateAfterInactivity);
if (defaultSocketConfig != null) {
poolingmgr.setDefaultSocketConfig(defaultSocketConfig);
}
+ if (socketConfigMap != null) {
+ socketConfigMap.forEach(poolingmgr::setSocketConfig);
+ }
+ if (defaultConnectionMgmtConfig != null) {
+ poolingmgr.setDefaultConnectionMgmtConfig(defaultConnectionMgmtConfig);
+ }
+ if (connectionMgmtConfigMap != null) {
+ connectionMgmtConfigMap.forEach(poolingmgr::setConnectionMgmtConfig);
+ }
if (maxConnTotal > 0) {
poolingmgr.setMaxTotal(maxConnTotal);
}
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 ad5c389..de8552e 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
@@ -29,6 +29,8 @@ package org.apache.hc.client5.http.impl.nio;
import java.net.InetSocketAddress;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
@@ -37,6 +39,7 @@ import java.util.concurrent.atomic.AtomicReference;
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.ConnectionMgmtConfig;
import org.apache.hc.client5.http.impl.ConnPoolSupport;
import org.apache.hc.client5.http.impl.ConnectionShutdownException;
import org.apache.hc.client5.http.nio.AsyncClientConnectionManager;
@@ -109,9 +112,10 @@ public class PoolingAsyncClientConnectionManager implements AsyncClientConnectio
private final ManagedConnPool<HttpRoute, ManagedAsyncClientConnection> pool;
private final AsyncClientConnectionOperator connectionOperator;
+ private final ConcurrentMap<HttpRoute, ConnectionMgmtConfig> connectionMgmtConfigMap;
private final AtomicBoolean closed;
- private volatile TimeValue validateAfterInactivity;
+ private volatile ConnectionMgmtConfig defaultConnectionMgmtConfig;
public PoolingAsyncClientConnectionManager() {
this(RegistryBuilder.<TlsStrategy>create()
@@ -175,6 +179,7 @@ public class PoolingAsyncClientConnectionManager implements AsyncClientConnectio
default:
throw new IllegalArgumentException("Unexpected PoolConcurrencyPolicy value: " + poolConcurrencyPolicy);
}
+ this.connectionMgmtConfigMap = new ConcurrentHashMap<>();
this.closed = new AtomicBoolean(false);
}
@@ -184,6 +189,7 @@ public class PoolingAsyncClientConnectionManager implements AsyncClientConnectio
final AsyncClientConnectionOperator connectionOperator) {
this.connectionOperator = Args.notNull(connectionOperator, "Connection operator");
this.pool = Args.notNull(pool, "Connection pool");
+ this.connectionMgmtConfigMap = new ConcurrentHashMap<>();
this.closed = new AtomicBoolean(false);
}
@@ -221,6 +227,8 @@ public class PoolingAsyncClientConnectionManager implements AsyncClientConnectio
LOG.debug("{} endpoint lease request ({}) {}", id, requestTimeout, ConnPoolSupport.formatStats(route, state, pool));
}
final ComplexFuture<AsyncConnectionEndpoint> resultFuture = new ComplexFuture<>(callback);
+ final ConnectionMgmtConfig connMgmtConfig = connectionMgmtConfigMap.getOrDefault(route,
+ defaultConnectionMgmtConfig != null ? defaultConnectionMgmtConfig : ConnectionMgmtConfig.DEFAULT);
final Future<PoolEntry<HttpRoute, ManagedAsyncClientConnection>> leaseFuture = pool.lease(
route, state, requestTimeout, new FutureCallback<PoolEntry<HttpRoute, ManagedAsyncClientConnection>>() {
@@ -242,7 +250,7 @@ public class PoolingAsyncClientConnectionManager implements AsyncClientConnectio
@Override
public void completed(final PoolEntry<HttpRoute, ManagedAsyncClientConnection> poolEntry) {
final ManagedAsyncClientConnection connection = poolEntry.getConnection();
- final TimeValue timeValue = PoolingAsyncClientConnectionManager.this.validateAfterInactivity;
+ final TimeValue timeValue = connMgmtConfig != null ? connMgmtConfig.getValidateAfterInactivity() : null;
if (TimeValue.isNonNegative(timeValue) && connection != null &&
poolEntry.getUpdated() + timeValue.toMilliseconds() <= System.currentTimeMillis()) {
final ProtocolVersion protocolVersion = connection.getProtocolVersion();
@@ -335,13 +343,12 @@ public class PoolingAsyncClientConnectionManager implements AsyncClientConnectio
public Future<AsyncConnectionEndpoint> connect(
final AsyncConnectionEndpoint endpoint,
final ConnectionInitiator connectionInitiator,
- final Timeout connectTimeout,
+ final Timeout timeout,
final Object attachment,
final HttpContext context,
final FutureCallback<AsyncConnectionEndpoint> callback) {
Args.notNull(endpoint, "Endpoint");
Args.notNull(connectionInitiator, "Connection initiator");
- Args.notNull(connectTimeout, "Timeout");
final InternalConnectionEndpoint internalEndpoint = cast(endpoint);
final ComplexFuture<AsyncConnectionEndpoint> resultFuture = new ComplexFuture<>(callback);
if (internalEndpoint.isConnected()) {
@@ -357,6 +364,12 @@ public class PoolingAsyncClientConnectionManager implements AsyncClientConnectio
host = route.getTargetHost();
}
final InetSocketAddress localAddress = route.getLocalSocketAddress();
+
+ final ConnectionMgmtConfig connMgmtConfig = connectionMgmtConfigMap.getOrDefault(route,
+ defaultConnectionMgmtConfig != null ? defaultConnectionMgmtConfig : ConnectionMgmtConfig.DEFAULT);
+
+ final Timeout connectTimeout = timeout != null ? timeout : connMgmtConfig.getConnectTimeout();
+
if (LOG.isDebugEnabled()) {
LOG.debug("{} connecting endpoint to {} ({})", ConnPoolSupport.getId(endpoint), host, connectTimeout);
}
@@ -369,6 +382,10 @@ public class PoolingAsyncClientConnectionManager implements AsyncClientConnectio
if (LOG.isDebugEnabled()) {
LOG.debug("{} connected {}", ConnPoolSupport.getId(endpoint), ConnPoolSupport.getId(connection));
}
+ final Timeout socketTimeout = connMgmtConfig.getSocketTimeout();
+ if (socketTimeout != null) {
+ connection.setSocketTimeout(socketTimeout);
+ }
poolEntry.assignConnection(connection);
resultFuture.completed(internalEndpoint);
} catch (final RuntimeException ex) {
@@ -462,8 +479,41 @@ public class PoolingAsyncClientConnectionManager implements AsyncClientConnectio
return pool.getStats(route);
}
+ /**
+ * @since 5.2
+ */
+ public ConnectionMgmtConfig getDefaultConnectionMgmtConfig() {
+ return defaultConnectionMgmtConfig;
+ }
+
+ /**
+ * @since 5.2
+ */
+ public void setDefaultConnectionMgmtConfig(final ConnectionMgmtConfig defaultConnectionMgmtConfig) {
+ this.defaultConnectionMgmtConfig = defaultConnectionMgmtConfig;
+ }
+
+ /**
+ * @since 5.2
+ */
+ public void setConnectionMgmtConfig(final HttpRoute route, final ConnectionMgmtConfig connectionMgmtConfig) {
+ connectionMgmtConfigMap.put(route, connectionMgmtConfig);
+ }
+
+ /**
+ * @since 5.2
+ */
+ public ConnectionMgmtConfig getConnectionMgmtConfig(final HttpRoute route) {
+ return connectionMgmtConfigMap.get(route);
+ }
+
+ /**
+ *
+ * @deprecated Use {@link #getDefaultConnectionMgmtConfig()}.
+ */
+ @Deprecated
public TimeValue getValidateAfterInactivity() {
- return validateAfterInactivity;
+ return defaultConnectionMgmtConfig != null ? defaultConnectionMgmtConfig.getValidateAfterInactivity() : null;
}
/**
@@ -472,9 +522,18 @@ public class PoolingAsyncClientConnectionManager implements AsyncClientConnectio
* FutureCallback)} leased} to the consumer. Negative values passed
* to this method disable connection validation. This check helps detect connections
* that have become stale (half-closed) while kept inactive in the pool.
+ *
+ * @deprecated Use {@link #setDefaultConnectionMgmtConfig(ConnectionMgmtConfig)}
*/
+ @Deprecated
public void setValidateAfterInactivity(final TimeValue validateAfterInactivity) {
- this.validateAfterInactivity = validateAfterInactivity;
+ defaultConnectionMgmtConfig = defaultConnectionMgmtConfig != null ?
+ ConnectionMgmtConfig.copy(defaultConnectionMgmtConfig)
+ .setValidateAfterInactivity(validateAfterInactivity)
+ .build() :
+ ConnectionMgmtConfig.custom()
+ .setValidateAfterInactivity(validateAfterInactivity)
+ .build();
}
private static final AtomicLong COUNT = new AtomicLong(0);
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 cafe7e4..8b19a99 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
@@ -27,8 +27,13 @@
package org.apache.hc.client5.http.impl.nio;
+import java.util.HashMap;
+import java.util.Map;
+
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.ConnectionMgmtConfig;
import org.apache.hc.client5.http.ssl.ConscryptClientTlsStrategy;
import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy;
import org.apache.hc.core5.http.config.RegistryBuilder;
@@ -77,8 +82,9 @@ public class PoolingAsyncClientConnectionManagerBuilder {
private int maxConnTotal;
private int maxConnPerRoute;
+ private ConnectionMgmtConfig defaultConnectionMgmtConfig;
+ private Map<HttpRoute, ConnectionMgmtConfig> connectionMgmtConfigMap;
private TimeValue timeToLive;
- private TimeValue validateAfterInactivity;
public static PoolingAsyncClientConnectionManagerBuilder create() {
return new PoolingAsyncClientConnectionManagerBuilder();
@@ -146,6 +152,29 @@ public class PoolingAsyncClientConnectionManagerBuilder {
}
/**
+ * Assigns default {@link ConnectionMgmtConfig}.
+ *
+ * @since 5.2
+ */
+ public final PoolingAsyncClientConnectionManagerBuilder setDefaultConnectionMgmtConfig(
+ final ConnectionMgmtConfig defaultConnectionMgmtConfig) {
+ this.defaultConnectionMgmtConfig = defaultConnectionMgmtConfig;
+ return this;
+ }
+
+ /**
+ * @since 5.2
+ */
+ public final PoolingAsyncClientConnectionManagerBuilder setConnectionMgmtConfig(final HttpRoute route,
+ final ConnectionMgmtConfig connectionMgmtConfig) {
+ if (connectionMgmtConfigMap == null) {
+ connectionMgmtConfigMap = new HashMap<>();
+ }
+ connectionMgmtConfigMap.put(route, connectionMgmtConfig);
+ return this;
+ }
+
+ /**
* Sets maximum time to live for persistent connections
*/
public final PoolingAsyncClientConnectionManagerBuilder setConnectionTimeToLive(final TimeValue timeToLive) {
@@ -157,10 +186,17 @@ public class PoolingAsyncClientConnectionManagerBuilder {
* Sets period after inactivity after which persistent
* connections must be checked to ensure they are still valid.
*
- * @see org.apache.hc.core5.http.io.HttpClientConnection#isStale()
+ * @deprecated Use {@link #setDefaultConnectionMgmtConfig(ConnectionMgmtConfig)}.
*/
+ @Deprecated
public final PoolingAsyncClientConnectionManagerBuilder setValidateAfterInactivity(final TimeValue validateAfterInactivity) {
- this.validateAfterInactivity = validateAfterInactivity;
+ defaultConnectionMgmtConfig = defaultConnectionMgmtConfig != null ?
+ ConnectionMgmtConfig.copy(defaultConnectionMgmtConfig)
+ .setValidateAfterInactivity(validateAfterInactivity)
+ .build() :
+ ConnectionMgmtConfig.custom()
+ .setValidateAfterInactivity(validateAfterInactivity)
+ .build();
return this;
}
@@ -201,7 +237,12 @@ public class PoolingAsyncClientConnectionManagerBuilder {
timeToLive,
schemePortResolver,
dnsResolver);
- poolingmgr.setValidateAfterInactivity(this.validateAfterInactivity);
+ if (defaultConnectionMgmtConfig != null) {
+ poolingmgr.setDefaultConnectionMgmtConfig(defaultConnectionMgmtConfig);
+ }
+ if (connectionMgmtConfigMap != null) {
+ connectionMgmtConfigMap.forEach(poolingmgr::setConnectionMgmtConfig);
+ }
if (maxConnTotal > 0) {
poolingmgr.setMaxTotal(maxConnTotal);
}
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/config/TestRequestConfig.java b/httpclient5/src/test/java/org/apache/hc/client5/http/config/TestRequestConfig.java
index e0035d8..572bba0 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/config/TestRequestConfig.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/config/TestRequestConfig.java
@@ -32,7 +32,6 @@ import java.util.concurrent.TimeUnit;
import org.apache.hc.client5.http.auth.StandardAuthScheme;
import org.apache.hc.client5.http.cookie.StandardCookieSpec;
-import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.util.TimeValue;
import org.apache.hc.core5.util.Timeout;
import org.junit.Assert;
@@ -49,7 +48,6 @@ public class TestRequestConfig {
@Test
public void testDefaults() {
final RequestConfig config = RequestConfig.DEFAULT;
- Assert.assertEquals(Timeout.ofMinutes(3), config.getConnectTimeout());
Assert.assertEquals(Timeout.ofMinutes(3), config.getConnectionRequestTimeout());
Assert.assertEquals(false, config.isExpectContinueEnabled());
Assert.assertEquals(true, config.isAuthenticationEnabled());
@@ -66,7 +64,6 @@ public class TestRequestConfig {
@Test
public void testBuildAndCopy() throws Exception {
final RequestConfig config0 = RequestConfig.custom()
- .setConnectTimeout(33, TimeUnit.MILLISECONDS)
.setConnectionRequestTimeout(44, TimeUnit.MILLISECONDS)
.setExpectContinueEnabled(true)
.setAuthenticationEnabled(false)
@@ -74,13 +71,11 @@ public class TestRequestConfig {
.setCircularRedirectsAllowed(true)
.setMaxRedirects(100)
.setCookieSpec(StandardCookieSpec.STRICT)
- .setProxy(new HttpHost("someproxy"))
.setTargetPreferredAuthSchemes(Collections.singletonList(StandardAuthScheme.NTLM))
.setProxyPreferredAuthSchemes(Collections.singletonList(StandardAuthScheme.DIGEST))
.setContentCompressionEnabled(false)
.build();
final RequestConfig config = RequestConfig.copy(config0).build();
- Assert.assertEquals(TimeValue.ofMilliseconds(33), config.getConnectTimeout());
Assert.assertEquals(TimeValue.ofMilliseconds(44), config.getConnectionRequestTimeout());
Assert.assertEquals(true, config.isExpectContinueEnabled());
Assert.assertEquals(false, config.isAuthenticationEnabled());
@@ -88,7 +83,6 @@ public class TestRequestConfig {
Assert.assertEquals(true, config.isCircularRedirectsAllowed());
Assert.assertEquals(100, config.getMaxRedirects());
Assert.assertEquals(StandardCookieSpec.STRICT, config.getCookieSpec());
- Assert.assertEquals(new HttpHost("someproxy"), config.getProxy());
Assert.assertEquals(Collections.singletonList(StandardAuthScheme.NTLM), config.getTargetPreferredAuthSchemes());
Assert.assertEquals(Collections.singletonList(StandardAuthScheme.DIGEST), config.getProxyPreferredAuthSchemes());
Assert.assertEquals(false, config.isContentCompressionEnabled());
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 7a61c7f..4c88c26 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
@@ -42,6 +42,7 @@ import org.apache.hc.client5.http.SystemDefaultDnsResolver;
import org.apache.hc.client5.http.auth.StandardAuthScheme;
import org.apache.hc.client5.http.auth.CredentialsProvider;
import org.apache.hc.client5.http.classic.methods.HttpGet;
+import org.apache.hc.client5.http.config.ConnectionMgmtConfig;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.cookie.BasicCookieStore;
import org.apache.hc.client5.http.cookie.StandardCookieSpec;
@@ -172,15 +173,17 @@ public class ClientConfiguration {
socketFactoryRegistry, PoolConcurrencyPolicy.STRICT, PoolReusePolicy.LIFO, TimeValue.ofMinutes(5),
null, dnsResolver, null);
- // Create socket configuration
- final SocketConfig socketConfig = SocketConfig.custom()
- .setTcpNoDelay(true)
- .build();
// Configure the connection manager to use socket configuration either
// by default or for a specific host.
- connManager.setDefaultSocketConfig(socketConfig);
- // Validate connections after 1 sec of inactivity
- connManager.setValidateAfterInactivity(TimeValue.ofSeconds(10));
+ connManager.setDefaultSocketConfig(SocketConfig.custom()
+ .setTcpNoDelay(true)
+ .build());
+ // Validate connections after 10 sec of inactivity
+ connManager.setDefaultConnectionMgmtConfig(ConnectionMgmtConfig.custom()
+ .setConnectTimeout(Timeout.ofSeconds(30))
+ .setSocketTimeout(Timeout.ofSeconds(30))
+ .setValidateAfterInactivity(TimeValue.ofSeconds(10))
+ .build());
// Configure total max or per route limits for persistent connections
// that can be kept in the pool or leased by the connection manager.
@@ -214,8 +217,6 @@ public class ClientConfiguration {
// They will take precedence over the one set at the client level.
final RequestConfig requestConfig = RequestConfig.copy(defaultRequestConfig)
.setConnectionRequestTimeout(Timeout.ofSeconds(5))
- .setConnectTimeout(Timeout.ofSeconds(5))
- .setProxy(new HttpHost("myotherproxy", 8080))
.build();
httpget.setConfig(requestConfig);