Batu Lab NotesPractical developer guides

Interpret a 204 response as having no body

By Batu ยท English technical notes

A 204 No Content result should produce no application-visible body. This example models a response entirely in BytesIO: a status line, one header, the terminating blank line, and deliberately trailing bytes. It reads the status line, converts 204 to HTTPStatus.NO_CONTENT, then collects only header lines through the blank line before calling BytesHeaderParser.parsebytes().

That boundary is deliberate. BytesParser.parse() reads all data from a file-like object, and BytesHeaderParser differs mainly by making header-only parsing the default. Passing the isolated header block to parsebytes() prevents the parser from consuming the trailing fixture bytes. The final assertion then reads those bytes solely to demonstrate that they remained in the stream; they are not treated as the 204 body. The printed result is therefore the status value followed by b''.

HTTPStatus provides named status-code constants and was added in Python 3.5; BytesHeaderParser was added in Python 3.3. Consequently, this complete example requires Python 3.5 or later. Python documents HTTPStatus in the http reference and documents both parsebytes() and BytesHeaderParser in the email parser reference.

This is a controlled fixture, not a full HTTP parser. It assumes an ASCII status line and CRLF-terminated headers, does not validate HTTP framing or malformed input, and does not establish what a server, proxy, or client library would do. The assertions only establish this example's branch and stream position. AI assistance was used to draft this article.

from email.parser import BytesHeaderParser
from http import HTTPStatus
from io import BytesIO

trailing_bytes = b"bytes-that-are-not-a-204-body"
raw_response = (
    b"HTTP/1.1 204 No Content\r\n"
    b"X-Request-Id: fixture-7\r\n"
    b"\r\n"
    + trailing_bytes
)
stream = BytesIO(raw_response)
status_line = stream.readline().decode("ascii").rstrip("\r\n")
status = HTTPStatus(int(status_line.split()[1]))

header_block = bytearray()
while True:
    line = stream.readline()
    header_block.extend(line)
    if line == b"\r\n":
        break

headers = BytesHeaderParser().parsebytes(header_block)
body = b"" if status is HTTPStatus.NO_CONTENT else stream.read()

assert headers["X-Request-Id"] == "fixture-7"
assert status is HTTPStatus.NO_CONTENT
assert body == b""
assert stream.read() == trailing_bytes
print(status.value, body)
204 b''