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

tballison pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tika.git


The following commit(s) were added to refs/heads/main by this push:
     new 08705ef9a0 keep configured timeouts on HttpFetcher requests (#3453)
08705ef9a0 is described below

commit 08705ef9a01d74043f422e88d59483c74b327b40
Author: Naveed <[email protected]>
AuthorDate: Fri Oct 30 21:06:14 2026 +0530

    keep configured timeouts on HttpFetcher requests (#3453)
    
    HttpFetcher and AtlassianJwtFetcher set a RequestConfig on every GET to
    apply maxRedirects. HttpClient uses a request's own config in place of
    the client default rather than merging the two, so the connect, socket
    and connection-request timeouts HttpClientFactory installs as the
    default never applied to a fetch. Start the per-request config from a
    copy of the factory's default.
    
    Generated-by: Claude Code (Claude Opus 5.5)
---
 .../org/apache/tika/client/HttpClientFactory.java  | 19 +++++++++++++-----
 .../fetcher/atlassianjwt/AtlassianJwtFetcher.java  |  2 +-
 .../atlassianjwt/AtlassianJwtFetcherTest.java      | 21 ++++++++++++++++++++
 .../tika/pipes/fetcher/http/HttpFetcher.java       |  2 +-
 .../tika/pipes/fetcher/http/HttpFetcherTest.java   | 23 ++++++++++++++++++++++
 5 files changed, 60 insertions(+), 7 deletions(-)

diff --git 
a/tika-pipes/tika-httpclient-commons/src/main/java/org/apache/tika/client/HttpClientFactory.java
 
b/tika-pipes/tika-httpclient-commons/src/main/java/org/apache/tika/client/HttpClientFactory.java
index 6416f99524..292f2ae065 100644
--- 
a/tika-pipes/tika-httpclient-commons/src/main/java/org/apache/tika/client/HttpClientFactory.java
+++ 
b/tika-pipes/tika-httpclient-commons/src/main/java/org/apache/tika/client/HttpClientFactory.java
@@ -300,11 +300,8 @@ public class HttpClientFactory {
         return builder.setConnectionManager(manager)
                 .evictExpiredConnections()
                 .setRedirectStrategy(new CustomRedirectStrategy())
-                
.setDefaultRequestConfig(RequestConfig.custom().setTargetPreferredAuthSchemes(
-                        Arrays.asList(AuthSchemes.BASIC, AuthSchemes.NTLM))
-                        .setConnectionRequestTimeout(requestTimeoutMillis)
-                        
.setConnectTimeout(connectTimeoutMillis).setSocketTimeout(socketTimeoutMillis)
-                        .build()).setKeepAliveStrategy(getKeepAliveStrategy())
+                .setDefaultRequestConfig(getDefaultRequestConfig())
+                .setKeepAliveStrategy(getKeepAliveStrategy())
                 .setSSLSocketFactory(sslsf)
                 .setSSLHostnameVerifier(verifySsl
                         ? 
SSLConnectionSocketFactory.getDefaultHostnameVerifier()
@@ -312,6 +309,18 @@ public class HttpClientFactory {
                 .build();
     }
 
+    /**
+     * The request config {@link #build()} installs as the client default. A 
config set on a
+     * request replaces that default rather than merging with it, so start one 
from a copy of this.
+     */
+    public RequestConfig getDefaultRequestConfig() {
+        return RequestConfig.custom().setTargetPreferredAuthSchemes(
+                        Arrays.asList(AuthSchemes.BASIC, AuthSchemes.NTLM))
+                .setConnectionRequestTimeout(requestTimeoutMillis)
+                
.setConnectTimeout(connectTimeoutMillis).setSocketTimeout(socketTimeoutMillis)
+                .build();
+    }
+
     private void addProxy(HttpClientBuilder builder) {
         if (!StringUtils.isBlank(proxyHost)) {
             HttpHost proxy = new HttpHost(proxyHost, proxyPort);
diff --git 
a/tika-pipes/tika-pipes-plugins/tika-pipes-atlassian-jwt/src/main/java/org/apache/tika/pipes/fetcher/atlassianjwt/AtlassianJwtFetcher.java
 
b/tika-pipes/tika-pipes-plugins/tika-pipes-atlassian-jwt/src/main/java/org/apache/tika/pipes/fetcher/atlassianjwt/AtlassianJwtFetcher.java
index 721fc1d0d6..4c668d7aaa 100644
--- 
a/tika-pipes/tika-pipes-plugins/tika-pipes-atlassian-jwt/src/main/java/org/apache/tika/pipes/fetcher/atlassianjwt/AtlassianJwtFetcher.java
+++ 
b/tika-pipes/tika-pipes-plugins/tika-pipes-atlassian-jwt/src/main/java/org/apache/tika/pipes/fetcher/atlassianjwt/AtlassianJwtFetcher.java
@@ -148,7 +148,7 @@ public class AtlassianJwtFetcher extends 
AbstractTikaExtension implements Fetche
     public TikaInputStream fetch(String fetchKey, Metadata metadata, 
ParseContext parseContext)
             throws IOException, TikaException {
         HttpGet get = new HttpGet(fetchKey);
-        RequestConfig requestConfig = RequestConfig.custom()
+        RequestConfig requestConfig = 
RequestConfig.copy(httpClientFactory.getDefaultRequestConfig())
                 .setMaxRedirects(config.getMaxRedirects())
                 .setRedirectsEnabled(config.getMaxRedirects() > 0).build();
         get.setConfig(requestConfig);
diff --git 
a/tika-pipes/tika-pipes-plugins/tika-pipes-atlassian-jwt/src/test/java/org/apache/tika/pipes/atlassianjwt/AtlassianJwtFetcherTest.java
 
b/tika-pipes/tika-pipes-plugins/tika-pipes-atlassian-jwt/src/test/java/org/apache/tika/pipes/atlassianjwt/AtlassianJwtFetcherTest.java
index 665beb38bf..675eabc6b2 100644
--- 
a/tika-pipes/tika-pipes-plugins/tika-pipes-atlassian-jwt/src/test/java/org/apache/tika/pipes/atlassianjwt/AtlassianJwtFetcherTest.java
+++ 
b/tika-pipes/tika-pipes-plugins/tika-pipes-atlassian-jwt/src/test/java/org/apache/tika/pipes/atlassianjwt/AtlassianJwtFetcherTest.java
@@ -17,10 +17,17 @@
 package org.apache.tika.pipes.atlassianjwt;
 
 import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.SocketTimeoutException;
+
 import org.junit.jupiter.api.Test;
 
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.parser.ParseContext;
 import org.apache.tika.pipes.fetcher.atlassianjwt.AtlassianJwtFetcher;
 import 
org.apache.tika.pipes.fetcher.atlassianjwt.config.AtlassianJwtFetcherConfig;
 
@@ -51,4 +58,18 @@ public class AtlassianJwtFetcherTest {
         
assertFalse(AtlassianJwtFetcherConfig.load("{\"verifySsl\":false}").isVerifySsl());
         assertTrue(AtlassianJwtFetcherConfig.load("{}").isVerifySsl());
     }
+
+    @Test
+    public void testSocketTimeoutAppliesToRequests() throws Exception {
+        AtlassianJwtFetcher fetcher = new AtlassianJwtFetcher(null, new 
AtlassianJwtFetcherConfig()
+                .setSocketTimeoutMillis(500)
+                .setOverallTimeoutMillis(10_000L));
+        fetcher.initialize();
+        // the backlog completes the handshake; nothing ever answers the 
request
+        try (ServerSocket silent = new ServerSocket(0, 50, 
InetAddress.getLoopbackAddress())) {
+            String url = "http://127.0.0.1:"; + silent.getLocalPort() + "/";
+            assertThrows(SocketTimeoutException.class,
+                    () -> fetcher.fetch(url, new Metadata(), new 
ParseContext()));
+        }
+    }
 }
diff --git 
a/tika-pipes/tika-pipes-plugins/tika-pipes-http/src/main/java/org/apache/tika/pipes/fetcher/http/HttpFetcher.java
 
b/tika-pipes/tika-pipes-plugins/tika-pipes-http/src/main/java/org/apache/tika/pipes/fetcher/http/HttpFetcher.java
index efaf6e0106..14e81f0f96 100644
--- 
a/tika-pipes/tika-pipes-plugins/tika-pipes-http/src/main/java/org/apache/tika/pipes/fetcher/http/HttpFetcher.java
+++ 
b/tika-pipes/tika-pipes-plugins/tika-pipes-http/src/main/java/org/apache/tika/pipes/fetcher/http/HttpFetcher.java
@@ -173,7 +173,7 @@ public class HttpFetcher extends AbstractTikaExtension 
implements Fetcher, Range
 
     private RequestConfig buildRequestConfig() {
         return RequestConfig
-                .custom()
+                .copy(httpClientFactory.getDefaultRequestConfig())
                 .setMaxRedirects(httpFetcherConfig.getMaxRedirects())
                 .setRedirectsEnabled(httpFetcherConfig.getMaxRedirects() > 0)
                 .build();
diff --git 
a/tika-pipes/tika-pipes-plugins/tika-pipes-http/src/test/java/org/apache/tika/pipes/fetcher/http/HttpFetcherTest.java
 
b/tika-pipes/tika-pipes-plugins/tika-pipes-http/src/test/java/org/apache/tika/pipes/fetcher/http/HttpFetcherTest.java
index 0a6501dd55..b5e0d7d793 100644
--- 
a/tika-pipes/tika-pipes-plugins/tika-pipes-http/src/test/java/org/apache/tika/pipes/fetcher/http/HttpFetcherTest.java
+++ 
b/tika-pipes/tika-pipes-plugins/tika-pipes-http/src/test/java/org/apache/tika/pipes/fetcher/http/HttpFetcherTest.java
@@ -24,6 +24,9 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.SocketTimeoutException;
 import java.nio.charset.Charset;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -48,6 +51,7 @@ import org.apache.http.HttpStatus;
 import org.apache.http.ProtocolVersion;
 import org.apache.http.StatusLine;
 import org.apache.http.client.HttpClient;
+import org.apache.http.client.config.RequestConfig;
 import org.apache.http.client.methods.CloseableHttpResponse;
 import org.apache.http.client.methods.HttpGet;
 import org.apache.http.client.methods.HttpUriRequest;
@@ -327,6 +331,23 @@ class HttpFetcherTest extends TikaTest {
         }
     }
 
+    @Test
+    public void testSocketTimeoutAppliesToRequests() throws Exception {
+        HttpFetcherConfig config = new HttpFetcherConfig()
+                .setSocketTimeoutMillis(500)
+                .setOverallTimeoutMillis(10_000L);
+        HttpFetcher fetcher = new HttpFetcher(null, config);
+        fetcher.initialize();
+        // the backlog completes the handshake; nothing ever answers the 
request
+        try (ServerSocket silent = new ServerSocket(0, 50, 
InetAddress.getLoopbackAddress())) {
+            String url = "http://127.0.0.1:"; + silent.getLocalPort() + "/";
+            assertThrows(SocketTimeoutException.class,
+                    () -> fetcher.fetch(url, new Metadata(), new 
ParseContext()));
+            assertThrows(SocketTimeoutException.class,
+                    () -> fetcher.fetch(url, 0, 10, new Metadata(), new 
ParseContext()));
+        }
+    }
+
     FetcherManager getFetcherManager(String path) throws Exception {
         Path configPath = 
Paths.get(HttpFetcherTest.class.getResource("/configs/" + path).toURI());
         TikaJsonConfig tikaJsonConfig = TikaJsonConfig.load(configPath);
@@ -369,6 +390,8 @@ class HttpFetcherTest extends TikaTest {
                 .when(clientFactory.build()).thenReturn(httpClient);
         Mockito
                 .when(clientFactory.copy()).thenReturn(clientFactory);
+        Mockito
+                
.when(clientFactory.getDefaultRequestConfig()).thenReturn(RequestConfig.DEFAULT);
 
         httpFetcher.setHttpClientFactory(clientFactory);
         httpFetcher.setHttpFetcherConfig(httpFetcherConfig);

Reply via email to