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/04/27 11:13:06 UTC
[httpcomponents-client] 04/04: Moved connection management related
settings from RequestConfig to new class ConnectionConfig
This is an automated email from the ASF dual-hosted git repository.
olegk pushed a commit to branch 5.2.x
in repository https://gitbox.apache.org/repos/asf/httpcomponents-client.git
commit 605f6c397cd60c1e3c33a19d9aa894137e2aafc1
Author: Oleg Kalnichevski <ol...@apache.org>
AuthorDate: Thu Mar 25 22:09:29 2021 +0100
Moved connection management related settings from RequestConfig to new class ConnectionConfig
---
.../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 +-
.../client5/testing/sync/LocalServerTestBase.java | 6 +-
.../hc/client5/http/config/ConnectionConfig.java | 205 +++++++++++++++++++++
.../hc/client5/http/config/RequestConfig.java | 23 ++-
.../http/impl/async/H2AsyncClientBuilder.java | 30 ++-
.../http/impl/async/InternalH2AsyncClient.java | 5 +-
.../impl/async/InternalH2AsyncExecRuntime.java | 9 +-
.../http/impl/async/InternalH2ConnPool.java | 102 ++++++++++
.../http/impl/async/MinimalH2AsyncClient.java | 16 +-
.../impl/io/BasicHttpClientConnectionManager.java | 29 ++-
.../io/PoolingHttpClientConnectionManager.java | 119 +++++++++---
.../PoolingHttpClientConnectionManagerBuilder.java | 61 ++++--
.../nio/PoolingAsyncClientConnectionManager.java | 83 ++++++---
...PoolingAsyncClientConnectionManagerBuilder.java | 40 +++-
.../hc/client5/http/config/TestRequestConfig.java | 6 -
.../client5/http/examples/ClientConfiguration.java | 19 +-
25 files changed, 691 insertions(+), 114 deletions(-)
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..964e1d3 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.ConnectionConfig;
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()
+ .setDefaultConnectionConfig(ConnectionConfig.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..a6795d1 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.ConnectionConfig;
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())
+ .setDefaultConnectionConfig(ConnectionConfig.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..c4697dd 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.ConnectionConfig;
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())
+ .setDefaultConnectionConfig(ConnectionConfig.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..52adf5a 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.ConnectionConfig;
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())
+ .setDefaultConnectionConfig(ConnectionConfig.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..989e51c 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.ConnectionConfig;
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())
+ .setDefaultConnectionConfig(ConnectionConfig.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 b76256c..38b12b8 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
@@ -32,6 +32,7 @@ import java.util.concurrent.Future;
import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder;
+import org.apache.hc.client5.http.config.ConnectionConfig;
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;
@@ -74,6 +75,10 @@ public class TestHttp1Async extends AbstractHttpAsyncFundamentalsTest<CloseableH
protected void before() throws Throwable {
connManager = PoolingAsyncClientConnectionManagerBuilder.create()
.setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext()))
+ .setDefaultConnectionConfig(ConnectionConfig.custom()
+ .setConnectTimeout(TIMEOUT)
+ .setSocketTimeout(TIMEOUT)
+ .build())
.build();
}
@@ -95,7 +100,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 67f3ca7..f0a2ba6 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.SimpleHttpResponse;
import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder;
+import org.apache.hc.client5.http.config.ConnectionConfig;
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()))
+ .setDefaultConnectionConfig(ConnectionConfig.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 fdbc72b..5d1cbb3 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.SimpleHttpResponse;
import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder;
+import org.apache.hc.client5.http.config.ConnectionConfig;
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;
@@ -68,6 +69,10 @@ public class TestHttp1AsyncStatefulConnManagement extends AbstractIntegrationTes
protected void before() throws Throwable {
connManager = PoolingAsyncClientConnectionManagerBuilder.create()
.setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext()))
+ .setDefaultConnectionConfig(ConnectionConfig.custom()
+ .setConnectTimeout(TIMEOUT)
+ .setSocketTimeout(TIMEOUT)
+ .build())
.build();
}
@@ -88,7 +93,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 4bfca6f..b4b049d 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
@@ -37,6 +37,7 @@ import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder;
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.ConnectionConfig;
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;
@@ -84,6 +85,10 @@ public class TestHttp1ClientAuthentication extends AbstractHttpAsyncClientAuthen
protected void before() throws Throwable {
connManager = PoolingAsyncClientConnectionManagerBuilder.create()
.setTlsStrategy(new DefaultClientTlsStrategy(SSLTestContexts.createClientSSLContext()))
+ .setDefaultConnectionConfig(ConnectionConfig.custom()
+ .setConnectTimeout(TIMEOUT)
+ .setSocketTimeout(TIMEOUT)
+ .build())
.build();
}
@@ -105,7 +110,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 eee59b5..02fd4f4 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.SimpleRequestBuilder;
+import org.apache.hc.client5.http.config.ConnectionConfig;
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()))
+ .setDefaultConnectionConfig(ConnectionConfig.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/sync/LocalServerTestBase.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/LocalServerTestBase.java
index 07a98b5..21486f7 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.ConnectionConfig;
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.setDefaultConnectionConfig(ConnectionConfig.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/ConnectionConfig.java b/httpclient5/src/main/java/org/apache/hc/client5/http/config/ConnectionConfig.java
new file mode 100644
index 0000000..97ed585
--- /dev/null
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/config/ConnectionConfig.java
@@ -0,0 +1,205 @@
+/*
+ * ====================================================================
+ * 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 ConnectionConfig implements Cloneable {
+
+ private static final Timeout DEFAULT_CONNECT_TIMEOUT = Timeout.ofMinutes(3);
+
+ public static final ConnectionConfig DEFAULT = new Builder().build();
+
+ private final Timeout connectTimeout;
+ private final Timeout socketTimeout;
+ private final TimeValue validateAfterInactivity;
+
+ /**
+ * Intended for CDI compatibility
+ */
+ protected ConnectionConfig() {
+ this(DEFAULT_CONNECT_TIMEOUT, null, null);
+ }
+
+ ConnectionConfig(
+ 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 ConnectionConfig clone() throws CloneNotSupportedException {
+ return (ConnectionConfig) 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 ConnectionConfig.Builder custom() {
+ return new Builder();
+ }
+
+ public static ConnectionConfig.Builder copy(final ConnectionConfig 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: {@code null}
+ * </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.
+ * <p>
+ * Default: {@code null}
+ * </p>
+ */
+ 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 ConnectionConfig build() {
+ return new ConnectionConfig(
+ 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..b3a7860 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 ConnectionConfig#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 ConnectionConfig.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 ConnectionConfig.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 6c2a0dc..494e925 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
@@ -45,6 +45,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.ConnectionConfig;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.cookie.BasicCookieStore;
import org.apache.hc.client5.http.cookie.CookieSpecFactory;
@@ -74,7 +75,9 @@ import org.apache.hc.client5.http.routing.HttpRoutePlanner;
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.function.Resolver;
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 +92,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 +191,7 @@ public class H2AsyncClientBuilder {
private String userAgent;
private Collection<? extends Header> defaultHeaders;
private RequestConfig defaultRequestConfig;
+ private Resolver<HttpHost, ConnectionConfig> connectionConfigResolver;
private boolean evictIdleConnections;
private TimeValue maxIdleTime;
@@ -501,6 +504,26 @@ public class H2AsyncClientBuilder {
}
/**
+ * Assigns {@link Resolver} for {@link ConnectionConfig} on a per host basis.
+ *
+ * @since 5.2
+ */
+ public final H2AsyncClientBuilder setConnectionConfigResolver(final Resolver<HttpHost, ConnectionConfig> connectionConfigResolver) {
+ this.connectionConfigResolver = connectionConfigResolver;
+ return this;
+ }
+
+ /**
+ * Assigns the same {@link ConnectionConfig} for all hosts.
+ *
+ * @since 5.2
+ */
+ public final H2AsyncClientBuilder setDefaultConnectionConfig(final ConnectionConfig connectionConfig) {
+ this.connectionConfigResolver = (host) -> connectionConfig;
+ return this;
+ }
+
+ /**
* Use system properties when creating and configuring default
* implementations.
*/
@@ -784,7 +807,8 @@ 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);
+ connPool.setConnectionConfigResolver(connectionConfigResolver);
List<Closeable> closeablesCopy = closeables != null ? new ArrayList<>(closeables) : null;
if (closeablesCopy == null) {
@@ -821,7 +845,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..fb089dd
--- /dev/null
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalH2ConnPool.java
@@ -0,0 +1,102 @@
+/*
+ * ====================================================================
+ * 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.ConnectionConfig;
+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.pool.H2ConnPool;
+import org.apache.hc.core5.io.CloseMode;
+import org.apache.hc.core5.io.ModalCloseable;
+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.Future;
+
+class InternalH2ConnPool implements ModalCloseable {
+
+ private final H2ConnPool connPool;
+
+ private volatile Resolver<HttpHost, ConnectionConfig> connectionConfigResolver;
+
+ InternalH2ConnPool(final ConnectionInitiator connectionInitiator,
+ final Resolver<HttpHost, InetSocketAddress> addressResolver,
+ final TlsStrategy tlsStrategy) {
+ this.connPool = new H2ConnPool(connectionInitiator, addressResolver, tlsStrategy);
+ }
+
+ public void close(final CloseMode closeMode) {
+ connPool.close(closeMode);
+ }
+
+ public void close() {
+ connPool.close();
+ }
+
+ private ConnectionConfig resolveConnectionConfig(final HttpHost httpHost) {
+ final Resolver<HttpHost, ConnectionConfig> resolver = this.connectionConfigResolver;
+ final ConnectionConfig connectionConfig = resolver != null ? resolver.resolve(httpHost) : null;
+ return connectionConfig != null ? connectionConfig : ConnectionConfig.DEFAULT;
+ }
+
+ public Future<IOSession> getSession(
+ final HttpHost endpoint,
+ final Timeout connectTimeout,
+ final FutureCallback<IOSession> callback) {
+ final ConnectionConfig connectionConfig = resolveConnectionConfig(endpoint);
+ return connPool.getSession(
+ endpoint,
+ connectTimeout != null ? connectTimeout : connectionConfig.getConnectTimeout(),
+ new CallbackContribution<IOSession>(callback) {
+
+ @Override
+ public void completed(final IOSession ioSession) {
+ final Timeout socketTimeout = connectionConfig.getSocketTimeout();
+ if (socketTimeout != null) {
+ ioSession.setSocketTimeout(socketTimeout);
+ }
+ callback.completed(ioSession);
+ }
+
+ });
+ }
+
+ public void closeIdle(final TimeValue idleTime) {
+ connPool.closeIdle(idleTime);
+ }
+
+ public void setConnectionConfigResolver(final Resolver<HttpHost, ConnectionConfig> connectionConfigResolver) {
+ this.connectionConfigResolver = connectionConfigResolver;
+ }
+
+}
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..fe0f7fd 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.ConnectionConfig;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.ConnPoolSupport;
import org.apache.hc.client5.http.impl.ExecSupport;
@@ -46,6 +47,7 @@ import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.concurrent.Cancellable;
import org.apache.hc.core5.concurrent.ComplexCancellable;
import org.apache.hc.core5.concurrent.FutureCallback;
+import org.apache.hc.core5.function.Resolver;
import org.apache.hc.core5.http.EntityDetails;
import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpException;
@@ -61,7 +63,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 +91,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 +113,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 +250,13 @@ public final class MinimalH2AsyncClient extends AbstractMinimalHttpAsyncClientBa
return cancellable;
}
+ /**
+ * Sets {@link Resolver} for {@link ConnectionConfig} on a per host basis.
+ *
+ * @since 5.2
+ */
+ public void setConnectionConfigResolver(final Resolver<HttpHost, ConnectionConfig> connectionConfigResolver) {
+ connPool.setConnectionConfigResolver(connectionConfigResolver);
+ }
+
}
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 230c304..337c1dc 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/BasicHttpClientConnectionManager.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/BasicHttpClientConnectionManager.java
@@ -39,6 +39,7 @@ import org.apache.hc.client5.http.DnsResolver;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.SchemePortResolver;
import org.apache.hc.client5.http.impl.ConnPoolSupport;
+import org.apache.hc.client5.http.config.ConnectionConfig;
import org.apache.hc.client5.http.impl.ConnectionShutdownException;
import org.apache.hc.client5.http.io.ConnectionEndpoint;
import org.apache.hc.client5.http.io.HttpClientConnectionManager;
@@ -107,6 +108,7 @@ public class BasicHttpClientConnectionManager implements HttpClientConnectionMan
private long expiry;
private boolean leased;
private SocketConfig socketConfig;
+ private ConnectionConfig connectionConfig;
private final AtomicBoolean closed;
@@ -187,6 +189,20 @@ public class BasicHttpClientConnectionManager implements HttpClientConnectionMan
this.socketConfig = socketConfig != null ? socketConfig : SocketConfig.DEFAULT;
}
+ /**
+ * @since 5.2
+ */
+ public synchronized ConnectionConfig getConnectionConfig() {
+ return connectionConfig;
+ }
+
+ /**
+ * @since 5.2
+ */
+ public synchronized void setConnectionConfig(final ConnectionConfig connectionConfig) {
+ this.connectionConfig = connectionConfig != null ? connectionConfig : ConnectionConfig.DEFAULT;
+ }
+
public LeaseRequest lease(final String id, final HttpRoute route, final Object state) {
return lease(id, route, Timeout.DISABLED, state);
}
@@ -328,7 +344,7 @@ public class BasicHttpClientConnectionManager implements HttpClientConnectionMan
}
@Override
- public void connect(final ConnectionEndpoint endpoint, final TimeValue connectTimeout, final HttpContext context) throws IOException {
+ public synchronized void connect(final ConnectionEndpoint endpoint, final TimeValue timeout, final HttpContext context) throws IOException {
Args.notNull(endpoint, "Endpoint");
final InternalConnectionEndpoint internalEndpoint = cast(endpoint);
@@ -342,17 +358,24 @@ public class BasicHttpClientConnectionManager implements HttpClientConnectionMan
} else {
host = route.getTargetHost();
}
+ final ConnectionConfig config = connectionConfig != null ? connectionConfig : ConnectionConfig.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
- public void upgrade(
+ public synchronized void upgrade(
final ConnectionEndpoint endpoint,
final HttpContext context) throws IOException {
Args.notNull(endpoint, "Endpoint");
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 13b3998..c6eeb27 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
@@ -26,19 +26,10 @@
*/
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.ExecutionException;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicLong;
-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.ConnectionConfig;
import org.apache.hc.client5.http.impl.ConnPoolSupport;
import org.apache.hc.client5.http.impl.ConnectionShutdownException;
import org.apache.hc.client5.http.io.ConnectionEndpoint;
@@ -52,6 +43,7 @@ import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.Internal;
import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.function.Resolver;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.HttpException;
@@ -80,6 +72,16 @@ import org.apache.hc.core5.util.Timeout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.IOException;
+import java.util.Set;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
+
/**
* {@code ClientConnectionPoolManager} maintains a pool of
* {@link ManagedHttpClientConnection}s and is able to service connection requests
@@ -112,8 +114,8 @@ public class PoolingHttpClientConnectionManager
private final HttpConnectionFactory<ManagedHttpClientConnection> connFactory;
private final AtomicBoolean closed;
- private volatile SocketConfig defaultSocketConfig;
- private volatile TimeValue validateAfterInactivity;
+ private volatile Resolver<HttpRoute, SocketConfig> socketConfigResolver;
+ private volatile Resolver<HttpRoute, ConnectionConfig> connectionConfigResolver;
public PoolingHttpClientConnectionManager() {
this(RegistryBuilder.<ConnectionSocketFactory>create()
@@ -203,7 +205,6 @@ public class PoolingHttpClientConnectionManager
}
this.connFactory = connFactory != null ? connFactory : ManagedHttpClientConnectionFactory.INSTANCE;
this.closed = new AtomicBoolean(false);
- this.validateAfterInactivity = TimeValue.ofSeconds(2L);
}
@Internal
@@ -241,6 +242,23 @@ public class PoolingHttpClientConnectionManager
throw new IllegalStateException("Unexpected endpoint class: " + endpoint.getClass());
}
+ private ConnectionConfig resolveConnectionConfig(final HttpRoute route) {
+ final Resolver<HttpRoute, ConnectionConfig> resolver = this.connectionConfigResolver;
+ final ConnectionConfig connectionConfig = resolver != null ? resolver.resolve(route) : null;
+ return connectionConfig != null ? connectionConfig : ConnectionConfig.DEFAULT;
+ }
+
+ private SocketConfig resolveSocketConfig(final HttpRoute route) {
+ final Resolver<HttpRoute, SocketConfig> resolver = this.socketConfigResolver;
+ final SocketConfig socketConfig = resolver != null ? resolver.resolve(route) : null;
+ return socketConfig != null ? socketConfig : SocketConfig.DEFAULT;
+ }
+
+ private TimeValue resolveValidateAfterInactivity(final ConnectionConfig connectionConfig) {
+ final TimeValue timeValue = connectionConfig.getValidateAfterInactivity();
+ return timeValue != null ? timeValue : TimeValue.ofSeconds(2);
+ }
+
public LeaseRequest lease(final String id, final HttpRoute route, final Object state) {
return lease(id, route, Timeout.DISABLED, state);
}
@@ -280,12 +298,13 @@ public class PoolingHttpClientConnectionManager
if (LOG.isDebugEnabled()) {
LOG.debug("{} endpoint leased {}", id, ConnPoolSupport.formatStats(route, state, pool));
}
+ final ConnectionConfig connectionConfig = resolveConnectionConfig(route);
+ final TimeValue timeValue = resolveValidateAfterInactivity(connectionConfig);
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();
@@ -382,7 +401,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()) {
@@ -399,21 +418,27 @@ public class PoolingHttpClientConnectionManager
} else {
host = route.getTargetHost();
}
+ final SocketConfig socketConfig = resolveSocketConfig(route);
+ final ConnectionConfig connectionConfig = resolveConnectionConfig(route);
+ final TimeValue connectTimeout = timeout != null ? timeout : connectionConfig.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,
context);
if (LOG.isDebugEnabled()) {
LOG.debug("{} connected {}", ConnPoolSupport.getId(endpoint), ConnPoolSupport.getId(conn));
}
+ final Timeout socketTimeout = connectionConfig.getSocketTimeout();
+ if (socketTimeout != null) {
+ conn.setSocketTimeout(socketTimeout);
+ }
}
@Override
@@ -485,21 +510,56 @@ public class PoolingHttpClientConnectionManager
return this.pool.getStats(route);
}
- public SocketConfig getDefaultSocketConfig() {
- return this.defaultSocketConfig;
+ /**
+ * Sets the same {@link SocketConfig} for all routes
+ */
+ public void setDefaultSocketConfig(final SocketConfig config) {
+ this.socketConfigResolver = (route) -> config;
}
- public void setDefaultSocketConfig(final SocketConfig defaultSocketConfig) {
- this.defaultSocketConfig = defaultSocketConfig;
+ /**
+ * Sets {@link Resolver} of {@link SocketConfig} on a per route basis.
+ *
+ * @since 5.2
+ */
+ public void setSocketConfigResolver(final Resolver<HttpRoute, SocketConfig> socketConfigResolver) {
+ this.socketConfigResolver = socketConfigResolver;
+ }
+
+ /**
+ * Sets the same {@link ConnectionConfig} for all routes
+ *
+ * @since 5.2
+ */
+ public void setDefaultConnectionConfig(final ConnectionConfig config) {
+ this.connectionConfigResolver = (route) -> config;
}
/**
- * @see #setValidateAfterInactivity(TimeValue)
+ * Sets {@link Resolver} of {@link ConnectionConfig} on a per route basis.
*
+ * @since 5.2
+ */
+ public void setConnectionConfigResolver(final Resolver<HttpRoute, ConnectionConfig> connectionConfigResolver) {
+ this.connectionConfigResolver = connectionConfigResolver;
+ }
+
+ /**
+ * @deprecated Use custom {@link #setConnectionConfigResolver(Resolver)}
+ */
+ @Deprecated
+ public SocketConfig getDefaultSocketConfig() {
+ return SocketConfig.DEFAULT;
+ }
+
+ /**
* @since 4.4
+ *
+ * @deprecated Use {@link #setConnectionConfigResolver(Resolver)}.
*/
+ @Deprecated
public TimeValue getValidateAfterInactivity() {
- return validateAfterInactivity;
+ return ConnectionConfig.DEFAULT.getValidateAfterInactivity();
}
/**
@@ -509,9 +569,14 @@ public class PoolingHttpClientConnectionManager
* detect connections that have become stale (half-closed) while kept inactive in the pool.
*
* @since 4.4
+ *
+ * @deprecated Use {@link #setConnectionConfigResolver(Resolver)}.
*/
+ @Deprecated
public void setValidateAfterInactivity(final TimeValue validateAfterInactivity) {
- this.validateAfterInactivity = validateAfterInactivity;
+ setDefaultConnectionConfig(ConnectionConfig.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 2dd506b..e52f9ac 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
@@ -28,12 +28,15 @@
package org.apache.hc.client5.http.impl.io;
import org.apache.hc.client5.http.DnsResolver;
+import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.SchemePortResolver;
+import org.apache.hc.client5.http.config.ConnectionConfig;
import org.apache.hc.client5.http.io.ManagedHttpClientConnection;
import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
import org.apache.hc.client5.http.socket.LayeredConnectionSocketFactory;
import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory;
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
+import org.apache.hc.core5.function.Resolver;
import org.apache.hc.core5.http.URIScheme;
import org.apache.hc.core5.http.config.RegistryBuilder;
import org.apache.hc.core5.http.io.HttpConnectionFactory;
@@ -76,7 +79,8 @@ public class PoolingHttpClientConnectionManagerBuilder {
private DnsResolver dnsResolver;
private PoolConcurrencyPolicy poolConcurrencyPolicy;
private PoolReusePolicy poolReusePolicy;
- private SocketConfig defaultSocketConfig;
+ private Resolver<HttpRoute, SocketConfig> socketConfigResolver;
+ private Resolver<HttpRoute, ConnectionConfig> connectionConfigResolver;
private boolean systemProperties;
@@ -84,7 +88,6 @@ public class PoolingHttpClientConnectionManagerBuilder {
private int maxConnPerRoute;
private TimeValue timeToLive;
- private TimeValue validateAfterInactivity;
public static PoolingHttpClientConnectionManagerBuilder create() {
return new PoolingHttpClientConnectionManagerBuilder();
@@ -161,10 +164,42 @@ public class PoolingHttpClientConnectionManagerBuilder {
}
/**
- * Assigns default {@link SocketConfig}.
+ * Assigns the same {@link SocketConfig} for all routes.
*/
public final PoolingHttpClientConnectionManagerBuilder setDefaultSocketConfig(final SocketConfig config) {
- this.defaultSocketConfig = config;
+ this.socketConfigResolver = (route) -> config;
+ return this;
+ }
+
+ /**
+ * Assigns {@link Resolver} of {@link SocketConfig} on a per route basis.
+ *
+ * @since 5.2
+ */
+ public final PoolingHttpClientConnectionManagerBuilder setSocketConfigResolver(
+ final Resolver<HttpRoute, SocketConfig> socketConfigResolver) {
+ this.socketConfigResolver = socketConfigResolver;
+ return this;
+ }
+
+ /**
+ * Assigns the same {@link ConnectionConfig} for all routes.
+ *
+ * @since 5.2
+ */
+ public final PoolingHttpClientConnectionManagerBuilder setDefaultConnectionConfig(final ConnectionConfig config) {
+ this.connectionConfigResolver = (route) -> config;
+ return this;
+ }
+
+ /**
+ * Assigns {@link Resolver} of {@link ConnectionConfig} on a per route basis.
+ *
+ * @since 5.2
+ */
+ public final PoolingHttpClientConnectionManagerBuilder setConnectionConfigResolver(
+ final Resolver<HttpRoute, ConnectionConfig> connectionConfigResolver) {
+ this.connectionConfigResolver = connectionConfigResolver;
return this;
}
@@ -180,10 +215,13 @@ 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 #setDefaultConnectionConfig(ConnectionConfig)}.
*/
+ @Deprecated
public final PoolingHttpClientConnectionManagerBuilder setValidateAfterInactivity(final TimeValue validateAfterInactivity) {
- this.validateAfterInactivity = validateAfterInactivity;
+ setDefaultConnectionConfig(ConnectionConfig.custom()
+ .setValidateAfterInactivity(validateAfterInactivity)
+ .build());
return this;
}
@@ -197,8 +235,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,12 +249,8 @@ public class PoolingHttpClientConnectionManagerBuilder {
schemePortResolver,
dnsResolver,
connectionFactory);
- if (validateAfterInactivity != null) {
- poolingmgr.setValidateAfterInactivity(validateAfterInactivity);
- }
- if (defaultSocketConfig != null) {
- poolingmgr.setDefaultSocketConfig(defaultSocketConfig);
- }
+ poolingmgr.setSocketConfigResolver(socketConfigResolver);
+ poolingmgr.setConnectionConfigResolver(connectionConfigResolver);
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 dc59ce8..21cb5b3 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
@@ -37,6 +37,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.ConnectionConfig;
import org.apache.hc.client5.http.impl.ConnPoolSupport;
import org.apache.hc.client5.http.impl.ConnectionShutdownException;
import org.apache.hc.client5.http.nio.AsyncClientConnectionManager;
@@ -49,6 +50,7 @@ import org.apache.hc.core5.annotation.Internal;
import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.concurrent.ComplexFuture;
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.HttpVersion;
import org.apache.hc.core5.http.ProtocolVersion;
@@ -111,7 +113,7 @@ public class PoolingAsyncClientConnectionManager implements AsyncClientConnectio
private final AsyncClientConnectionOperator connectionOperator;
private final AtomicBoolean closed;
- private volatile TimeValue validateAfterInactivity;
+ private volatile Resolver<HttpRoute, ConnectionConfig> connectionConfigResolver;
public PoolingAsyncClientConnectionManager() {
this(RegistryBuilder.<TlsStrategy>create()
@@ -210,6 +212,12 @@ public class PoolingAsyncClientConnectionManager implements AsyncClientConnectio
throw new IllegalStateException("Unexpected endpoint class: " + endpoint.getClass());
}
+ private ConnectionConfig resolveConnectionConfig(final HttpRoute route) {
+ final Resolver<HttpRoute, ConnectionConfig> resolver = this.connectionConfigResolver;
+ final ConnectionConfig connectionConfig = resolver != null ? resolver.resolve(route) : null;
+ return connectionConfig != null ? connectionConfig : ConnectionConfig.DEFAULT;
+ }
+
@Override
public Future<AsyncConnectionEndpoint> lease(
final String id,
@@ -221,6 +229,7 @@ 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 ConnectionConfig connectionConfig = resolveConnectionConfig(route);
final Future<PoolEntry<HttpRoute, ManagedAsyncClientConnection>> leaseFuture = pool.lease(
route, state, requestTimeout, new FutureCallback<PoolEntry<HttpRoute, ManagedAsyncClientConnection>>() {
@@ -242,25 +251,20 @@ public class PoolingAsyncClientConnectionManager implements AsyncClientConnectio
@Override
public void completed(final PoolEntry<HttpRoute, ManagedAsyncClientConnection> poolEntry) {
final ManagedAsyncClientConnection connection = poolEntry.getConnection();
- if (connection != null) {
- if (connection.isOpen()) {
- final ProtocolVersion protocolVersion = connection.getProtocolVersion();
- if (protocolVersion != null && protocolVersion.greaterEquals(HttpVersion.HTTP_2_0)) {
- final TimeValue timeValue = PoolingAsyncClientConnectionManager.this.validateAfterInactivity;
- if (TimeValue.isNonNegative(timeValue) &&
- poolEntry.getUpdated() + timeValue.toMilliseconds() <= System.currentTimeMillis()) {
- connection.submitCommand(new PingCommand(new BasicPingHandler(result -> {
- if (result == null || !result) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("{} connection {} is stale", id, ConnPoolSupport.getId(connection));
- }
- poolEntry.discardConnection(CloseMode.IMMEDIATE);
- }
- leaseCompleted(poolEntry);
- })), Command.Priority.IMMEDIATE);
- return;
+ final TimeValue timeValue = connectionConfig != null ? connectionConfig.getValidateAfterInactivity() : null;
+ if (TimeValue.isNonNegative(timeValue) && connection != null &&
+ poolEntry.getUpdated() + timeValue.toMilliseconds() <= System.currentTimeMillis()) {
+ final ProtocolVersion protocolVersion = connection.getProtocolVersion();
+ if (protocolVersion != null && protocolVersion.greaterEquals(HttpVersion.HTTP_2_0)) {
+ connection.submitCommand(new PingCommand(new BasicPingHandler(result -> {
+ if (result == null || !result) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("{} connection {} is stale", id, ConnPoolSupport.getId(connection));
+ }
+ poolEntry.discardConnection(CloseMode.IMMEDIATE);
}
- }
+ leaseCompleted(poolEntry);
+ })), Command.Priority.IMMEDIATE);
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("{} connection {} is closed", id, ConnPoolSupport.getId(connection));
@@ -336,13 +340,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()) {
@@ -358,6 +361,9 @@ public class PoolingAsyncClientConnectionManager implements AsyncClientConnectio
host = route.getTargetHost();
}
final InetSocketAddress localAddress = route.getLocalSocketAddress();
+ final ConnectionConfig connectionConfig = resolveConnectionConfig(route);
+ final Timeout connectTimeout = timeout != null ? timeout : connectionConfig.getConnectTimeout();
+
if (LOG.isDebugEnabled()) {
LOG.debug("{} connecting endpoint to {} ({})", ConnPoolSupport.getId(endpoint), host, connectTimeout);
}
@@ -370,6 +376,10 @@ public class PoolingAsyncClientConnectionManager implements AsyncClientConnectio
if (LOG.isDebugEnabled()) {
LOG.debug("{} connected {}", ConnPoolSupport.getId(endpoint), ConnPoolSupport.getId(connection));
}
+ final Timeout socketTimeout = connectionConfig.getSocketTimeout();
+ if (socketTimeout != null) {
+ connection.setSocketTimeout(socketTimeout);
+ }
poolEntry.assignConnection(connection);
resultFuture.completed(internalEndpoint);
} catch (final RuntimeException ex) {
@@ -463,8 +473,30 @@ public class PoolingAsyncClientConnectionManager implements AsyncClientConnectio
return pool.getStats(route);
}
+ /**
+ * Sets the same {@link ConnectionConfig} for all routes
+ *
+ * @since 5.2
+ */
+ public void setDefaultConnectionConfig(final ConnectionConfig config) {
+ this.connectionConfigResolver = (route) -> config;
+ }
+
+ /**
+ * Sets {@link Resolver} of {@link ConnectionConfig} on a per route basis.
+ *
+ * @since 5.2
+ */
+ public void setConnectionConfigResolver(final Resolver<HttpRoute, ConnectionConfig> connectionConfigResolver) {
+ this.connectionConfigResolver = connectionConfigResolver;
+ }
+
+ /**
+ * @deprecated Use custom {@link #setConnectionConfigResolver(Resolver)}
+ */
+ @Deprecated
public TimeValue getValidateAfterInactivity() {
- return validateAfterInactivity;
+ return ConnectionConfig.DEFAULT.getValidateAfterInactivity();
}
/**
@@ -473,9 +505,14 @@ 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 #setConnectionConfigResolver(Resolver)}.
*/
+ @Deprecated
public void setValidateAfterInactivity(final TimeValue validateAfterInactivity) {
- this.validateAfterInactivity = validateAfterInactivity;
+ setDefaultConnectionConfig(ConnectionConfig.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 c1dd8ae..a8d44b0 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
@@ -28,10 +28,14 @@
package org.apache.hc.client5.http.impl.nio;
import org.apache.hc.client5.http.DnsResolver;
+import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.SchemePortResolver;
+import org.apache.hc.client5.http.config.ConnectionConfig;
import org.apache.hc.client5.http.ssl.ConscryptClientTlsStrategy;
import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy;
+import org.apache.hc.core5.function.Resolver;
import org.apache.hc.core5.http.config.RegistryBuilder;
+import org.apache.hc.core5.http.io.SocketConfig;
import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
import org.apache.hc.core5.pool.PoolConcurrencyPolicy;
import org.apache.hc.core5.pool.PoolReusePolicy;
@@ -77,8 +81,9 @@ public class PoolingAsyncClientConnectionManagerBuilder {
private int maxConnTotal;
private int maxConnPerRoute;
+ private Resolver<HttpRoute, SocketConfig> socketConfigResolver;
+ private Resolver<HttpRoute, ConnectionConfig> connectionConfigResolver;
private TimeValue timeToLive;
- private TimeValue validateAfterInactivity;
public static PoolingAsyncClientConnectionManagerBuilder create() {
return new PoolingAsyncClientConnectionManagerBuilder();
@@ -146,6 +151,28 @@ public class PoolingAsyncClientConnectionManagerBuilder {
}
/**
+ * Assigns the same {@link ConnectionConfig} for all routes.
+ *
+ * @since 5.2
+ */
+ public final PoolingAsyncClientConnectionManagerBuilder setDefaultConnectionConfig(final ConnectionConfig config) {
+ this.connectionConfigResolver = (route) -> config;
+ return this;
+ }
+
+ /**
+ * Assigns {@link Resolver} of {@link ConnectionConfig} on a per route basis.
+ *
+ * @since 5.2
+ */
+ public final PoolingAsyncClientConnectionManagerBuilder setConnectionConfigResolver(
+ final Resolver<HttpRoute, ConnectionConfig> connectionConfigResolver) {
+ this.connectionConfigResolver = connectionConfigResolver;
+ return this;
+ }
+
+
+ /**
* Sets maximum time to live for persistent connections
*/
public final PoolingAsyncClientConnectionManagerBuilder setConnectionTimeToLive(final TimeValue timeToLive) {
@@ -157,10 +184,13 @@ 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 #setConnectionConfigResolver(Resolver)}.
*/
+ @Deprecated
public final PoolingAsyncClientConnectionManagerBuilder setValidateAfterInactivity(final TimeValue validateAfterInactivity) {
- this.validateAfterInactivity = validateAfterInactivity;
+ setDefaultConnectionConfig(ConnectionConfig.custom()
+ .setValidateAfterInactivity(validateAfterInactivity)
+ .build());
return this;
}
@@ -201,9 +231,7 @@ public class PoolingAsyncClientConnectionManagerBuilder {
timeToLive,
schemePortResolver,
dnsResolver);
- if (validateAfterInactivity != null) {
- poolingmgr.setValidateAfterInactivity(validateAfterInactivity);
- }
+ poolingmgr.setConnectionConfigResolver(connectionConfigResolver);
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..4ec5ab2 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.ConnectionConfig;
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.setDefaultConnectionConfig(ConnectionConfig.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);