mirror of
https://github.com/caddyserver/caddy.git
synced 2026-10-31 08:21:39 -04:00
* caddyhttp: only bound HTTP/2 body reads in flight with the idle timeout On HTTP/2, the read deadline is a timer that fails the request body when it fires, even with no read in flight. IdleTimeoutReader left the idle deadline armed between reads, so a handler that stopped reading for longer than read_body_idle (1 minute by default) lost the body, although the client was only held back by flow control. For example, reverse_proxy uploading to an upstream that's slow to accept the body failed with a 502. This is the read side of #8118. Like IdleTimeoutWriter does since read on HTTP/2, so the idle deadline only bounds reads in flight. A client that stops sending is still cut off, since the deadline is set before each read. HTTP/1 and HTTP/3 only check the deadline during a read, so they're unchanged. Written with Claude Code (Claude Opus 5.5); the human submitter is responsible for reviewing it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * caddyhttp: track a released hard read deadline as armed From review: with HardDeadline set, releasing the idle deadline between reads left an HTTP/2 timer armed (at HardDeadline) while deadlineSet recorded that none was, so clearDeadlineLocked would skip clearing it. Track which deadline is armed (none, idle, or only the hard one) instead of a bool, and have each check ask the question it means: re-arming and releasing only apply to an armed idle deadline, while clearing applies to any. The writer's deadlineSet already only means "idle deadline armed", since nothing clears the hard deadline it leaves; document that. Written with Claude Code (Claude Opus 5.5); the human submitter is responsible for reviewing it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * caddyhttp: clear released hard deadline at handler end, skip no-op sets From review: - After a partial read releases the idle deadline to HardDeadline, a handler that returns without reading again left that timer armed past HandlerDone, which only cleared after a terminal error. HandlerDone now also clears a released hard deadline. - When the idle deadline is capped to HardDeadline, the reader and writer set the same deadline again when releasing it, and the writer once more in HandlerDone. On HTTP/2 each is a message to the serve loop. Both now remember the deadline they armed and skip setting it again. Within a request, only these wrappers set the client's deadlines. Replaces the earlier test that faked a terminal error with the partial read followed directly by HandlerDone. Written with Claude Code (Claude Opus 5.5); the human submitter is responsible for reviewing it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * caddyhttp: only skip re-setting an armed hard deadline Skipping any deadline equal to the one already armed also skipped idle deadlines on Windows, where two calls to time.Now in the same clock tick return the same time, so successive idle deadlines can be equal. That broke tests counting deadline calls there. Only skip HardDeadline, the case from review where the idle deadline is capped to it; other deadlines are always set. Written with Claude Code (Claude Opus 5.5); the human submitter is responsible for reviewing it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * caddyhttp: restore deadlines without trusting cached transport state Always set the requested read and write deadlines because another handler can change them through its own response controller. Remove the armedAt shortcut and cover intervening deadline changes for reads, writes, ReadFrom, flushes, and HandlerDone. AI-assisted with OpenAI Codex (GPT-6); tested under human direction. --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>