You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by rs...@apache.org on 2026/01/18 20:17:37 UTC
(httpcomponents-client) 02/02: DefaultManagedHttpClientConnection: Restore original socket timeout
This is an automated email from the ASF dual-hosted git repository.
rschmitt pushed a commit to branch 5.6.x
in repository https://gitbox.apache.org/repos/asf/httpcomponents-client.git
commit 8fdd72edd8c5d081484b85dfdaa5aa7ba6e34708
Author: Ryan Schmitt <rs...@apache.org>
AuthorDate: Wed Jan 14 17:24:45 2026 -0800
DefaultManagedHttpClientConnection: Restore original socket timeout
This change fixes a bug in the synchronous client where socket timeouts
were not being set correctly on reused connections, and the client was
instead setting it to either the TLS handshake timeout or the
`responseTimeout` from the `RequestConfig` of the previous request.
The fix works by changing `DefaultManagedHttpClientConnection` to store
the `socketTimeout` set on the socket at the time `bind` is called, and
always restore that value when the `activate` method is called. Note
that this requires the caller to call `setSoTimeout` on the socket
_before_ binding the connection to it, hence the adjustments to some of
the code in `DefaultHttpClientConnectionOperator`.
---
.../testing/async/TestAsyncSocketTimeout.java | 32 ++++++++++------------
.../hc/client5/testing/sync/TestSocketTimeout.java | 16 +++++++----
.../io/DefaultHttpClientConnectionOperator.java | 4 +--
.../io/DefaultManagedHttpClientConnection.java | 1 -
4 files changed, 27 insertions(+), 26 deletions(-)
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncSocketTimeout.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncSocketTimeout.java
index ee17bb9cf..aae0ecb1b 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncSocketTimeout.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestAsyncSocketTimeout.java
@@ -38,7 +38,6 @@
import org.apache.hc.core5.http.Method;
import org.apache.hc.core5.http.URIScheme;
import org.apache.hc.core5.io.CloseMode;
-import org.apache.hc.core5.util.VersionInfo;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Timeout;
import org.junit.jupiter.params.ParameterizedTest;
@@ -51,7 +50,6 @@
import static org.apache.hc.core5.util.ReflectionUtils.determineJRELevel;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assumptions.assumeFalse;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
abstract class AbstractTestSocketTimeout extends AbstractIntegrationTestBase {
@@ -83,21 +81,26 @@ void testReadTimeouts(final int connConfigTimeout, final int responseTimeout) th
}
for (final boolean drip : new boolean[]{ false, true }) {
- final SimpleHttpRequest request = getRequest(responseTimeout, drip,
- target);
-
- final Throwable cause = assertThrows(ExecutionException.class, () -> client.execute(request, null).get())
- .getCause();
- assertInstanceOf(SocketTimeoutException.class, cause);
+ for (final boolean reuseConnection : new boolean[]{ false, true }) {
+ if (reuseConnection) {
+ client.execute(getRequest(2500, 0, false, target), null).get();
+ }
+ final SimpleHttpRequest request = getRequest(responseTimeout, 2500, drip, target);
+
+ final Throwable cause = assertThrows(ExecutionException.class,
+ () -> client.execute(request, null).get()).getCause();
+ assertInstanceOf(SocketTimeoutException.class, cause,
+ String.format("drip=%s, reuseConnection=%s", drip, reuseConnection));
+ }
}
closeClient(client);
}
- private SimpleHttpRequest getRequest(final int responseTimeout, final boolean drip, final HttpHost target)
- throws Exception {
+ private SimpleHttpRequest getRequest(final int responseTimeout, final int delay, final boolean drip,
+ final HttpHost target) throws Exception {
final SimpleHttpRequest request = SimpleHttpRequest.create(Method.GET, target,
- "/random/10240?delay=2500&drip=" + (drip ? 1 : 0));
+ "/random/10240?delay=" + delay + "&drip=" + (drip ? 1 : 0));
if (responseTimeout > 0) {
request.setConfig(RequestConfig.custom()
.setUnixDomainSocket(getUnixDomainSocket())
@@ -138,13 +141,6 @@ public Uds() {
@Override
void checkAssumptions() {
assumeTrue(determineJRELevel() >= 16, "Async UDS requires Java 16+");
- final String[] components = VersionInfo
- .loadVersionInfo("org.apache.hc.core5", getClass().getClassLoader())
- .getRelease()
- .split("[-.]");
- final int majorVersion = Integer.parseInt(components[0]);
- final int minorVersion = Integer.parseInt(components[1]);
- assumeFalse(majorVersion <= 5 && minorVersion <= 3, "Async UDS requires HttpCore 5.4+");
}
}
}
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestSocketTimeout.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestSocketTimeout.java
index 56bd63008..bb8caa2aa 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestSocketTimeout.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestSocketTimeout.java
@@ -85,15 +85,21 @@ void testReadTimeouts(final int socketConfigTimeout, final int connConfigTimeout
}
for (final boolean drip : new boolean[]{ false, true }) {
- final HttpGet request = getRequest(responseTimeout, drip);
+ for (final boolean reuseConnection : new boolean[]{ false, true }) {
+ if (reuseConnection) {
+ client.execute(target, getRequest(5000, 0, false), new BasicHttpClientResponseHandler());
+ }
+ final HttpGet request = getRequest(responseTimeout, 2500, drip);
- assertThrows(SocketTimeoutException.class, () ->
- client.execute(target, request, new BasicHttpClientResponseHandler()));
+ assertThrows(SocketTimeoutException.class, () ->
+ client.execute(target, request, new BasicHttpClientResponseHandler()),
+ String.format("drip=%s, reuseConnection=%s", drip, reuseConnection));
+ }
}
}
- private HttpGet getRequest(final int responseTimeout, final boolean drip) throws Exception {
- final HttpGet request = new HttpGet(new URI("/random/10240?delay=2500&drip=" + (drip ? 1 : 0)));
+ private HttpGet getRequest(final int responseTimeout, final int delay, final boolean drip) throws Exception {
+ final HttpGet request = new HttpGet(new URI("/random/10240?delay=" + delay + "&drip=" + (drip ? 1 : 0)));
if (responseTimeout > 0) {
request.setConfig(RequestConfig.custom()
.setUnixDomainSocket(getUnixDomainSocket())
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/DefaultHttpClientConnectionOperator.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/DefaultHttpClientConnectionOperator.java
index d1e31cddd..e0986ce9e 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/DefaultHttpClientConnectionOperator.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/DefaultHttpClientConnectionOperator.java
@@ -261,8 +261,8 @@ private void upgradeToTls(final ManagedHttpClientConnection conn, final HttpHost
socket.setSoTimeout(handshakeTimeout.toMillisecondsIntBound());
}
final SSLSocket sslSocket = tlsSocketStrategy.upgrade(socket, tlsName.getHostName(), tlsName.getPort(), attachment, context);
- conn.bind(sslSocket, socket);
socket.setSoTimeout(soTimeout);
+ conn.bind(sslSocket, socket);
onAfterTlsHandshake(context, endpointHost);
if (LOG.isDebugEnabled()) {
LOG.debug("{} {} upgraded to TLS", ConnPoolSupport.getId(conn), tlsName);
@@ -287,8 +287,8 @@ private void connectToUnixDomainSocket(
conn.bind(newSocket);
final Socket socket = unixDomainSocketFactory.connectSocket(newSocket, unixDomainSocket,
connectTimeout);
- conn.bind(socket);
configureSocket(socket, socketConfig, false);
+ conn.bind(socket);
onAfterSocketConnect(context, endpointHost);
if (LOG.isDebugEnabled()) {
LOG.debug("{} {} connected to {}", ConnPoolSupport.getId(conn), endpointHost, unixDomainSocket);
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/DefaultManagedHttpClientConnection.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/DefaultManagedHttpClientConnection.java
index f5fb1f69f..1a9f27bba 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/DefaultManagedHttpClientConnection.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/io/DefaultManagedHttpClientConnection.java
@@ -166,7 +166,6 @@ public void setSocketTimeout(final Timeout timeout) {
LOG.debug("{} set socket timeout to {}", this.id, timeout);
}
super.setSocketTimeout(timeout);
- socketTimeout = timeout;
}
@Override