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

sebastian-nagel pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nutch.git


The following commit(s) were added to refs/heads/master by this push:
     new a6159ea8e NUTCH-3174 protocol-okhttp: request may hang despite 
http.time.limit is set
a6159ea8e is described below

commit a6159ea8e071735a553f7b2758096ef7b071adb4
Author: Sebastian Nagel <[email protected]>
AuthorDate: Thu May 7 15:16:10 2026 +0200

    NUTCH-3174 protocol-okhttp: request may hang despite http.time.limit is set
    
    - set OkHttp's call timeout to the value of http.time.limit (if not -1)
    - add check whether http.time.limit is longer than http.timeout
    - more verbose logging
---
 .../org/apache/nutch/protocol/http/api/HttpBase.java  | 19 +++++++++++++------
 .../java/org/apache/nutch/protocol/okhttp/OkHttp.java |  5 +++++
 .../apache/nutch/protocol/okhttp/OkHttpResponse.java  |  8 +++++++-
 3 files changed, 25 insertions(+), 7 deletions(-)

diff --git 
a/src/plugin/lib-http/src/java/org/apache/nutch/protocol/http/api/HttpBase.java 
b/src/plugin/lib-http/src/java/org/apache/nutch/protocol/http/api/HttpBase.java
index caa3f861e..63b9224b0 100755
--- 
a/src/plugin/lib-http/src/java/org/apache/nutch/protocol/http/api/HttpBase.java
+++ 
b/src/plugin/lib-http/src/java/org/apache/nutch/protocol/http/api/HttpBase.java
@@ -223,6 +223,12 @@ public abstract class HttpBase implements Protocol {
     this.timeout = conf.getInt("http.timeout", 10000);
     this.maxContent = conf.getInt("http.content.limit", 1024 * 1024);
     this.maxDuration = conf.getInt("http.time.limit", -1);
+    if (maxDuration >= 0 && (maxDuration * 1000) < timeout) {
+      LOG.warn(
+          "The configuration property http.time.limit ({} seconds) is less 
than http.timeout ({} ms), "
+              + "the entire request will time out before individual reads are 
timed out.",
+          maxDuration, timeout);
+    }
     this.partialAsTruncated = conf.getBoolean("http.partial.truncated", false);
     this.userAgent = getAgentString(conf.get("http.agent.name"),
         conf.get("http.agent.version"), conf.get("http.agent.description"),
@@ -272,8 +278,8 @@ public abstract class HttpBase implements Protocol {
         }
 
       } catch (Exception e) {
-        this.logger.warn("Failed to read http.agent.rotate.file {}: {}", 
agentsFile,
-            StringUtils.stringifyException(e));
+        this.logger.warn("Failed to read http.agent.rotate.file {}:",
+            agentsFile, e);
         this.userAgentNames = null;
       } finally {
         if (br != null) {
@@ -314,8 +320,8 @@ public abstract class HttpBase implements Protocol {
           }
         }
       } catch (Exception e) {
-        this.logger.warn("Failed to read http.agent.host.cookie.file {}: {}",
-            cookieFile, StringUtils.stringifyException(e));
+        this.logger.warn("Failed to read http.agent.host.cookie.file {}:",
+            cookieFile, e);
         this.hostCookies = null;
       } finally {
         if (br != null) {
@@ -614,8 +620,9 @@ public abstract class HttpBase implements Protocol {
       this.logger.info("http.proxy.host = {}", this.proxyHost);
       this.logger.info("http.proxy.port = {}", this.proxyPort);
       this.logger.info("http.proxy.exception.list = {}", this.useProxy);
-      this.logger.info("http.timeout = {}", this.timeout);
-      this.logger.info("http.content.limit = {}", this.maxContent);
+      this.logger.info("http.timeout = {} ms", this.timeout);
+      this.logger.info("http.time.limit = {} seconds", this.maxDuration);
+      this.logger.info("http.content.limit = {} bytes", this.maxContent);
       this.logger.info("http.agent = {}", this.userAgent);
       this.logger.info("http.accept.language = {}", this.acceptLanguage);
       this.logger.info("http.accept = {}", this.accept);
diff --git 
a/src/plugin/protocol-okhttp/src/java/org/apache/nutch/protocol/okhttp/OkHttp.java
 
b/src/plugin/protocol-okhttp/src/java/org/apache/nutch/protocol/okhttp/OkHttp.java
index 8c898a0e2..be26886fe 100644
--- 
a/src/plugin/protocol-okhttp/src/java/org/apache/nutch/protocol/okhttp/OkHttp.java
+++ 
b/src/plugin/protocol-okhttp/src/java/org/apache/nutch/protocol/okhttp/OkHttp.java
@@ -121,6 +121,11 @@ public class OkHttp extends HttpBase {
         .writeTimeout(this.timeout, TimeUnit.MILLISECONDS)
         .readTimeout(this.timeout, TimeUnit.MILLISECONDS);
 
+    if (this.maxDuration >= 0) {
+      // timeout for the entire request
+      builder.callTimeout(this.maxDuration, TimeUnit.SECONDS);
+    }
+
     if (!this.tlsCheckCertificate) {
       try {
         SSLContext trustAllSslContext = SSLContext.getInstance("TLS");
diff --git 
a/src/plugin/protocol-okhttp/src/java/org/apache/nutch/protocol/okhttp/OkHttpResponse.java
 
b/src/plugin/protocol-okhttp/src/java/org/apache/nutch/protocol/okhttp/OkHttpResponse.java
index 7616bc886..8d7966199 100644
--- 
a/src/plugin/protocol-okhttp/src/java/org/apache/nutch/protocol/okhttp/OkHttpResponse.java
+++ 
b/src/plugin/protocol-okhttp/src/java/org/apache/nutch/protocol/okhttp/OkHttpResponse.java
@@ -17,6 +17,7 @@
 package org.apache.nutch.protocol.okhttp;
 
 import java.io.IOException;
+import java.io.InterruptedIOException;
 import java.lang.invoke.MethodHandles;
 import java.net.URL;
 import java.util.Base64;
@@ -186,7 +187,12 @@ public class OkHttpResponse implements Response {
       } catch (IOException e) {
         if (partialAsTruncated && source.getBuffer().size() > 0) {
           // treat already fetched content as truncated
-          truncated.setReason(TruncatedContentReason.DISCONNECT);
+          if (e instanceof InterruptedIOException) {
+            // thrown by OkHttp if the call timeout is hit
+            truncated.setReason(TruncatedContentReason.TIME);
+          } else {
+            truncated.setReason(TruncatedContentReason.DISCONNECT);
+          }
           LOG.info("Truncated content for {}, partial fetch caused by:", 
this.url,
               e);
         } else {

Reply via email to