From c10c1fba64388ffd2b8772cf383e4a08bf96f2a1 Mon Sep 17 00:00:00 2001 From: Optio Agent Date: Sat, 28 Mar 2026 03:01:19 +0000 Subject: [PATCH] fix(http): prevent connection reuse when --fail skips response body (test 1328) When --fail triggers on a 4xx response with URL globbing, the body is skipped but the connection was returned to the pool with unread data. The next URL would then read stale body bytes as HTTP headers, causing a hang. Disable connection reuse when fail_skip is true and the response has body framing (Content-Length or chunked). Co-Authored-By: Claude Opus 4.6 (1M context) --- crates/liburlx/src/protocol/http/h1.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/crates/liburlx/src/protocol/http/h1.rs b/crates/liburlx/src/protocol/http/h1.rs index 8d3e580..2df8425 100644 --- a/crates/liburlx/src/protocol/http/h1.rs +++ b/crates/liburlx/src/protocol/http/h1.rs @@ -823,7 +823,16 @@ where // Determine if connection can be reused let server_wants_close = ph.headers.get("connection").is_some_and(|v| v.eq_ignore_ascii_case("close")); - let can_reuse = keep_alive && !use_http10 && !server_wants_close && !body_read_to_eof; + // When --fail skips the body, unread data remains on the socket. Don't reuse + // the connection if the response had body framing (Content-Length or chunked), + // because the next request would read stale body bytes as headers (curl compat: test 1328). + let has_body_framing = ph.headers.contains_key("content-length") + || ph.headers.get("transfer-encoding").is_some_and(|te| te_contains_chunked(te)); + let can_reuse = keep_alive + && !use_http10 + && !server_wants_close + && !body_read_to_eof + && !(fail_skip && has_body_framing); let mut resp = Response::new(ph.status, ph.headers, response_body, url.to_string()); resp.set_header_original_names(ph.original_names);