Repository navigation
Conversation
RFC 9113 section 8.1.1 lists 204, 304 and the response to HEAD as messages defined to have no content, and allows a non-zero content-length. Only HEAD was exempt, so a 304 or 204 with content-length was accepted when END_STREAM was on HEADERS but rejected with an empty DATA frame. Concretize the header block once and apply the same exemption to 204/304.
|
Is this a duplicate of the same issue from #1332? |
|
Yes — same issue as #1332, and it was opened first (6 October), so I am closing this in its favour. How I checked, rather than assumingOur route treats The one case here that #1332 does not have is the control that a Thanks for asking rather than just closing it. |
|
Closing in favour of #1332, which was opened first and fixes the same thing: a 204/304 carrying a Thanks for asking instead of just closing it, and sorry for the duplicate review load. |
What is wrong
RFC 9113 § 8.1.1 defines 204, 304 and the response to HEAD as messages that have no content, and says such a message may carry a non-zero
content-length.H2Stream._initialize_content_length()only exemptsself.request_method == b"HEAD", so the other two statuses are judged by framing alone:The same applies to 204. This rejects a legitimate response depending only on which frame carried END_STREAM.
What changes
receive_headers()now concretizes the header block once, then_initialize_content_length()treats a response whose:statusis 204 or 304 like the HEAD exemption: expected content length is zero, so a bodyless message is accepted and any actual DATA is still rejected. Concretizing the block also avoids re-iterating a generator across informational-status, content-length and header-validation passes.Tests
New
tests/test_bodyless_responses.py:content-length: 1234and an empty DATA END_STREAM are accepted;InvalidBodyLengthError;On the parent revision the two empty-DATA bodyless cases fail with
InvalidBodyLengthError; with the change all 6 pass. Full suite: 1668 passed.ruff check src/andmypy --strict src/h2/stream.pyare clean.