fix(proxy): recompute Content-Length when replaying a modified body (#816)

build_raw_request kept the Content-Length inherited from the captured
request, so replaying a modified body (repeat_request) emitted a request
whose declared length did not match the body — truncating the payload or
stalling the target. Drop any inherited Content-Length (case-insensitively)
and recompute it from the body actually being sent.

Adds tests covering a lengthened body, an emptied body, and the
no-inherited-header path.

Fixes #814

Co-authored-by: thejesh23 <thejesh23@users.noreply.github.com>
This commit is contained in:
Thejesh Reddy
2026-07-20 21:43:49 -04:00
committed by GitHub
co-authored by thejesh23
parent 8cd9abba21
commit 599f7c7526
2 changed files with 43 additions and 1 deletions
+37
View File
@@ -140,6 +140,43 @@ async def test_host_call_serializes_concurrent_calls() -> None:
assert state["max"] == 1
def _headers_named(raw: bytes, name: str) -> list[str]:
head = raw.decode("utf-8").split("\r\n\r\n", 1)[0]
return [
line.split(":", 1)[1].strip()
for line in head.split("\r\n")[1:]
if line.split(":", 1)[0].strip().lower() == name.lower()
]
def test_build_raw_request_recomputes_content_length_for_modified_body() -> None:
# The captured request declared Content-Length: 12 (original body); the
# replayed body is longer. The emitted request must carry exactly one
# Content-Length equal to the ACTUAL body length, or the target truncates
# the modified payload (or the connection desyncs).
body = '{"user":"a\' OR 1=1 -- injected long payload"}'
_conn, raw = caido_api.build_raw_request(
method="POST",
url="https://example.com/login",
headers={"content-length": "12", "Content-Type": "application/json"},
body=body,
)
sent_body = raw.decode("utf-8").split("\r\n\r\n", 1)[1]
assert sent_body == body
assert _headers_named(raw, "Content-Length") == [str(len(body.encode("utf-8")))]
def test_build_raw_request_drops_stale_content_length_for_empty_body() -> None:
# A body cleared to empty must not keep the inherited (non-zero) length.
_conn, raw = caido_api.build_raw_request(
method="POST",
url="https://example.com/x",
headers={"Content-Length": "12"},
body="",
)
assert _headers_named(raw, "Content-Length") == []
class _Ctx:
def __init__(self, context: Any) -> None:
self.context = context