HTTP/1.1 Codec
The HTTP/1.1 codec handles request parsing, response serialization, and body framing. It uses httparse for zero-copy header parsing.
Request Parsing
Http1Codec::read_request() reads from the downstream stream until it has complete headers, then parses them via httparse. The parser operates on &[u8] slices from the read buffer — no header bytes are copied into owned buffers on the hot path.
Read buffer: [GET /api HTTP/1.1\r\nHost: example.com\r\n\r\n]
^
httparse borrows slices: method="GET", path="/api", headers=[...]
(zero-copy: pointers into the buffer)
Body Framing
After headers are parsed, determine_body_framing() decides how to read the body:
| Condition | Body Treatment |
|---|---|
| No Content-Length or Transfer-Encoding | No body |
Content-Length: N | Read exactly N bytes |
Transfer-Encoding: chunked | Dechunk (hex-size + CRLF + data + CRLF) |
| Both CL and TE present | Rejected (request smuggling prevention) |
| Multiple Content-Length values | Rejected (desync prevention) |
| Content-Length with whitespace | Rejected (padding desync prevention) |
Chunked Transfer Encoding
The dechunker reads chunks in a loop:
- Read chunk-size line (hex + optional extensions + CRLF)
- Read that many bytes of chunk data
- Read trailing CRLF
- Repeat until chunk-size is 0
- Consume optional trailers + final CRLF
Maximum body size is enforced (default 16MB) using overflow-safe arithmetic.
Request Smuggling Prevention
Meridian implements strict parsing per RFC 9110:
- CL+TE rejection: Both
Content-LengthandTransfer-Encodingpresent = immediate rejection - Duplicate CL rejection: Multiple
Content-Lengthheaders = rejection - Whitespace CL rejection:
Content-Length: 42(trailing space) = rejection - TE validation: Only
chunkedis accepted; other encodings are rejected
These checks are fuzz-tested with 7 dedicated fuzzing targets, including a differential smuggling fuzzer that generates adversarial header combinations.
Generic Stream I/O
All codec functions accept S: AsyncRead + AsyncWrite + Unpin instead of concrete TcpStream. This allows the same parsing code to work on:
- Plain TCP connections
- TLS-wrapped connections (
TlsStream<TcpStream>) - Test duplex streams
- Any future transport type