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 9f78c72cb NUTCH-3173 protocol-okhttp: store OkHttp's internal URL in 
response metadata (#919)
9f78c72cb is described below

commit 9f78c72cb1a5b69205d33e2b29039a45b680404b
Author: Luca <[email protected]>
AuthorDate: Sun Jun 7 16:57:46 2026 +0200

    NUTCH-3173 protocol-okhttp: store OkHttp's internal URL in response 
metadata (#919)
---
 src/java/org/apache/nutch/net/protocols/Response.java  |  2 +-
 src/java/org/apache/nutch/protocol/Protocol.java       | 13 +++++++++++++
 .../nutch/protocol/http/api/HttpRobotRulesParser.java  |  3 ++-
 .../apache/nutch/protocol/httpclient/HttpResponse.java | 11 +++++++++++
 .../java/org/apache/nutch/protocol/okhttp/OkHttp.java  | 18 ++++++++++++++++++
 .../apache/nutch/protocol/okhttp/OkHttpResponse.java   | 11 +++++++++--
 6 files changed, 54 insertions(+), 4 deletions(-)

diff --git a/src/java/org/apache/nutch/net/protocols/Response.java 
b/src/java/org/apache/nutch/net/protocols/Response.java
index 3fbe93266..2f5278437 100644
--- a/src/java/org/apache/nutch/net/protocols/Response.java
+++ b/src/java/org/apache/nutch/net/protocols/Response.java
@@ -85,7 +85,7 @@ public interface Response extends HttpHeaders {
   };
 
   /**
-   * Get the URL used to retrieve this response.
+   * Get the URL the protocol actually used when requesting the Response.
    * @return {@link java.net.URL}
    */
   public URL getUrl();
diff --git a/src/java/org/apache/nutch/protocol/Protocol.java 
b/src/java/org/apache/nutch/protocol/Protocol.java
index 2514eae33..34805febb 100644
--- a/src/java/org/apache/nutch/protocol/Protocol.java
+++ b/src/java/org/apache/nutch/protocol/Protocol.java
@@ -16,6 +16,7 @@
  */
 package org.apache.nutch.protocol;
 
+import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.List;
 
@@ -40,6 +41,18 @@ public interface Protocol extends Pluggable, Configurable {
    */
   ProtocolOutput getProtocolOutput(Text url, CrawlDatum datum);
 
+/**
+   * Resolve a relative URL against a base URL using the protocol's URL
+   * library.
+   *
+   * @param base the base URL the relative URL is resolved against
+   * @param relative the relative URL string (typically a Location: header 
value)
+   * @return resolved absolute URL
+   * @throws MalformedURLException if the URL is malformed
+   */
+  default URL resolveUrl(URL base, String relative) throws 
MalformedURLException {
+    return new URL(base, relative);
+  }
   /**
    * Retrieve robot rules applicable for this URL.
    *
diff --git 
a/src/plugin/lib-http/src/java/org/apache/nutch/protocol/http/api/HttpRobotRulesParser.java
 
b/src/plugin/lib-http/src/java/org/apache/nutch/protocol/http/api/HttpRobotRulesParser.java
index 9da92698f..7c5d8aa0a 100644
--- 
a/src/plugin/lib-http/src/java/org/apache/nutch/protocol/http/api/HttpRobotRulesParser.java
+++ 
b/src/plugin/lib-http/src/java/org/apache/nutch/protocol/http/api/HttpRobotRulesParser.java
@@ -170,7 +170,8 @@ public class HttpRobotRulesParser extends RobotRulesParser {
             LOG.debug("Following robots.txt redirect: {} -> {}", 
robotsUrlRedir,
                 redirectionLocation);
             try {
-              robotsUrlRedir = new URL(robotsUrlRedir, redirectionLocation);
+              robotsUrlRedir = ((HttpBase) http).resolveUrl(robotsUrlRedir,
+                  redirectionLocation);
             } catch (MalformedURLException e) {
               LOG.info(
                   "Failed to resolve redirect location for robots.txt: {} -> 
{} ({})",
diff --git 
a/src/plugin/protocol-httpclient/src/java/org/apache/nutch/protocol/httpclient/HttpResponse.java
 
b/src/plugin/protocol-httpclient/src/java/org/apache/nutch/protocol/httpclient/HttpResponse.java
index 87ee0bb8a..a7109bce4 100644
--- 
a/src/plugin/protocol-httpclient/src/java/org/apache/nutch/protocol/httpclient/HttpResponse.java
+++ 
b/src/plugin/protocol-httpclient/src/java/org/apache/nutch/protocol/httpclient/HttpResponse.java
@@ -121,6 +121,17 @@ public class HttpResponse implements Response {
       client.getParams().setParameter("http.useragent", http.getUserAgent()); 
// NUTCH-1941
       code = client.executeMethod(get);
 
+      // When followRedirects=true HC3 walks the redirect chain internally;
+      // getURI() returns the final URI. Capture it so getUrl() honors the
+      // contract — without this, robots.txt redirects via this plugin
+      // report the original URL even though a different URL was fetched.
+      try {
+        this.url = new URL(get.getURI().toString());
+      } catch (org.apache.commons.httpclient.URIException
+          | java.net.MalformedURLException e) {
+        // Keep the input URL or try to normalize it?
+      }
+
       Header[] heads = get.getResponseHeaders();
 
       for (int i = 0; i < heads.length; i++) {
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 a9d2b14d4..8c898a0e2 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
@@ -20,6 +20,7 @@ import java.io.IOException;
 import java.lang.invoke.MethodHandles;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
+import java.net.MalformedURLException;
 import java.net.Proxy;
 import java.net.ProxySelector;
 import java.net.SocketAddress;
@@ -58,6 +59,7 @@ import okhttp3.ConnectionPool;
 import okhttp3.Gzip;
 import okhttp3.Handshake;
 import okhttp3.Headers;
+import okhttp3.HttpUrl;
 import okhttp3.Interceptor;
 import okhttp3.OkHttpClient;
 import okhttp3.Protocol;
@@ -436,6 +438,22 @@ public class OkHttp extends HttpBase {
     return new OkHttpResponse(this, url, datum);
   }
 
+  /**
+   * Resolve a relative URL using OkHttp's {@link HttpUrl} parser, which is
+   * more lenient than Java's {@link URL} (handles malformed protocol-relative
+   * slashes such as {@code https:////host/path}, IDN→punycode, host case
+   * normalization, etc.). Falls back to Java URL if HttpUrl cannot parse.
+   */
+  @Override
+  public URL resolveUrl(URL base, String relative) throws 
MalformedURLException {
+    HttpUrl baseHttpUrl = HttpUrl.get(base);
+    HttpUrl resolved = baseHttpUrl.resolve(relative);
+    if (resolved != null) {
+      return resolved.url();
+    }
+    return super.resolveUrl(base, relative);
+  }
+
   public static void main(String[] args) throws Exception {
     OkHttp okhttp = new OkHttp();
     okhttp.setConf(NutchConfiguration.create());
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 605c03390..7616bc886 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
@@ -71,7 +71,7 @@ public class OkHttpResponse implements Response {
   public OkHttpResponse(OkHttp okhttp, URL url, CrawlDatum datum)
       throws ProtocolException, IOException {
 
-    this.url = url;
+    this.url = url;  // provisional; overwritten below with the normalized form
 
     Request.Builder rb = new Request.Builder().url(url);
 
@@ -102,7 +102,14 @@ public class OkHttpResponse implements Response {
     }
 
     Request request = rb.build();
-    okhttp3.Call call = okhttp.getClient(url).newCall(request);
+
+    // OkHttp parsed the URL via HttpUrl; that's the form actually going on
+    // the wire (IDN→punycode, repeated-slash repair, host lowercasing).
+    this.url = request.url().url();
+    if (LOG.isDebugEnabled() && !this.url.toString().equals(url.toString())) {
+       LOG.debug("The normalized URL different from the requested URL: {} -> 
{}", url, this.url);
+    }
+    okhttp3.Call call = okhttp.getClient(this.url).newCall(request);
 
     // ensure that Response and underlying ResponseBody are closed
     try (okhttp3.Response response = call.execute()) {

Reply via email to