blackbull.fault_injection.catalogue.h1_client¶
blackbull.fault_injection.catalogue.h1_client
¶
HTTP/1.1 client faults assembled as raw bytes. Do not reuse the production request encoder: it cannot expose its own defects.
absent_host()
¶
No Host header. RFC 9112 §3.2 makes this a 400.
bare_lf_terminators()
¶
Bare LF instead of CRLF (RFC 9112 §2.2 makes recognising it a MAY).
Implementations legitimately differ, which is exactly why it belongs in a catalogue: the case is here to make the difference visible, not to assert one answer.
body_shorter_than_declared()
¶
Declares 100 bytes of body and sends 5, then stops.
chunk_size_not_hex()
¶
A chunk size that is not hexadecimal (RFC 9112 §7.1).
content_length_and_transfer_encoding()
¶
Both framing headers at once — RFC 9112 §6.1 says reject.
The classic CL.TE / TE.CL desync: whichever one the recipient honours determines where it thinks the body ends.
duplicate_transfer_encoding()
¶
Two Transfer-Encoding headers, the second not chunked.
head_never_ends()
¶
Headers that never reach the terminating CRLFCRLF.
negative_content_length()
¶
Content-Length: -1 — not a valid length.
nul_in_header_value()
¶
A NUL byte in a field value — not a valid field-vchar.
obs_fold_header()
¶
An obs-fold continuation line (RFC 9112 §5.2 deprecates it).
oversized_method_token()
¶
A 2 KiB method token — a head-budget case, not a parse case.
space_before_header_colon()
¶
Foo : bar — RFC 9112 §5.1 requires rejecting, not trimming.
Trimming is the defect: a proxy that trims and an origin that rejects see different header sets.
trickled_head()
¶
The request head one byte at a time — the slowloris primitive.
Nothing here is malformed; the fault is the rate, which is why the server's answer comes from its header deadline rather than its parser.
two_content_lengths()
¶
Two Content-Length headers that disagree (RFC 9112 §6.3).
The smuggling primitive: a recipient that picks one and a recipient that picks the other disagree about where the next request starts.