Batu Lab NotesPractical developer guides

Split HTTP headers from a byte response fixture

By Batu · English technical notes

Also published in our primary archive.

Split HTTP headers from a byte response fixture

A complete HTTP response has a start line, header fields, a blank line, and then body bytes. This controlled fixture places HTTP/1.1 200 OK, two headers, and the JSON bytes {} in one value. bytes.partition(b"\r\n\r\n") splits only at the first header/body separator, so the body stays as bytes instead of being accidentally treated as another header line.

The header section still includes the start line. The code separates it at the first CRLF, then splits each remaining field once at :. Header names and values are decoded as ASCII only after the byte boundaries have been established. The assertions verify the selected status line, content type, trace value, and untouched body. The printed line is deterministic. No newer API is used; these established bytes and dictionary operations work on supported Python 3 releases.

This is a deliberately small fixture splitter, not a general HTTP parser. It accepts only the simple Name: value layout used here; it does not validate status-line grammar, folded or duplicate fields, non-ASCII header encodings, field-size limits, transfer coding, or whether Content-Type matches the body. The assertions establish facts about this fixture only. For broader header parsing, Python documents that http.client.parse_headers() expects an already-consumed start line and valid RFC 5322-style fields. No network connection is opened.

See Python’s bytes.partition() documentation and http.client.parse_headers() documentation.

AI-assistance disclosure: AI assisted the drafting of this educational example.

fixture = (
    b"HTTP/1.1 200 OK\r\n"
    b"Content-Type: application/json\r\n"
    b"X-Trace: demo-42\r\n"
    b"\r\n"
    b"{}"
)

head, separator, body = fixture.partition(b"\r\n\r\n")
assert separator == b"\r\n\r\n"
status_line, header_lines = head.split(b"\r\n", 1)
headers = {}
for line in header_lines.split(b"\r\n"):
    name, value = line.split(b":", 1)
    headers[name.decode("ascii")] = value.lstrip(b" ").decode("ascii")

assert status_line == b"HTTP/1.1 200 OK"
assert headers["Content-Type"] == "application/json"
assert headers["X-Trace"] == "demo-42"
assert body == b"{}"

print(status_line.decode("ascii"), headers["Content-Type"], body.decode("ascii"))
HTTP/1.1 200 OK application/json {}