luigidemasi commented on code in PR #143:
URL: https://github.com/apache/camel-kit/pull/143#discussion_r4440812813


##########
knowledge/mcp/src/main/java/org/apache/camel/kit/knowledge/mcp/IndexDownloader.java:
##########
@@ -568,9 +603,41 @@ private InputStream openStream(URI uri) throws 
IOException, InterruptedException
     }
 
     private HttpResponse<InputStream> send(HttpRequest request) throws 
IOException, InterruptedException {
+        final int maxRedirects = 5;
         long deadline = System.nanoTime() + 
request.timeout().orElseThrow().toNanos();
-        return httpClient.send(request, info -> 
HttpResponse.BodySubscribers.mapping(
-                HttpResponse.BodySubscribers.ofPublisher(), publisher -> new 
TimedBody(publisher, deadline)));
+        HttpRequest current = request;
+        for (int hop = 0;; hop++) {
+            HttpResponse<InputStream> response = httpClient.send(current, info 
-> HttpResponse.BodySubscribers.mapping(
+                    HttpResponse.BodySubscribers.ofPublisher(), publisher -> 
new TimedBody(publisher, deadline)));
+            int status = response.statusCode();
+            if (status != 301 && status != 302 && status != 303 && status != 
307 && status != 308) {
+                return response;
+            }
+            // Validate the redirect target's transport BEFORE following it; a 
304 is not a redirect and
+            // is returned above for the conditional-manifest path.
+            String target = 
response.headers().firstValue("Location").orElse(null);
+            response.body().close();
+            if (hop >= maxRedirects) {
+                throw new IOException("Too many index redirects starting from 
" + request.uri());
+            }
+            if (target == null) {
+                throw new IOException("Index redirect without a Location 
header from " + current.uri());
+            }
+            URI next;
+            try {
+                next = current.uri().resolve(target);
+            } catch (IllegalArgumentException e) {
+                throw new IOException("Invalid index redirect target: " + 
target, e);
+            }
+            requireFetchableUri(next);
+            long remaining = deadline - System.nanoTime();
+            if (remaining <= 0) {
+                throw new HttpTimeoutException("Index redirect handling timed 
out from " + request.uri());
+            }
+            HttpRequest.Builder builder = 
HttpRequest.newBuilder(next).timeout(Duration.ofNanos(remaining)).GET();
+            current.headers().firstValue("Accept").ifPresent(accept -> 
builder.header("Accept", accept));
+            current = builder.build();

Review Comment:
   [P2] Preserve the manifest validator when following redirects
   
   Rebuilding the request copies only `Accept`, dropping the `If-None-Match` 
header added by `fetchManifest()`. A manifest behind even a same-origin 302 
therefore downloads again on every resolution instead of returning 304 when 
unchanged.
   
   I reproduced this with a local redirect/manifest server: first resolve 
returns 200 with `ETag: "v1"`; on the second resolve, the target receives 
`If-None-Match: "v1"` and returns 304 at `88430bb6`, but receives no validator 
and returns 200 at this head. Forwarding that one header makes the same probe 
pass. The installed archive is still reused; the regression is conditional 
manifest revalidation.
   
   Please preserve `If-None-Match` across the validated redirect hops and add a 
two-resolution regression test that requires the target's 304 response.
   
   _AI-generated by Codex on behalf of @luigidemasi._
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to