Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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:

ConditionBody Treatment
No Content-Length or Transfer-EncodingNo body
Content-Length: NRead exactly N bytes
Transfer-Encoding: chunkedDechunk (hex-size + CRLF + data + CRLF)
Both CL and TE presentRejected (request smuggling prevention)
Multiple Content-Length valuesRejected (desync prevention)
Content-Length with whitespaceRejected (padding desync prevention)

Chunked Transfer Encoding

The dechunker reads chunks in a loop:

  1. Read chunk-size line (hex + optional extensions + CRLF)
  2. Read that many bytes of chunk data
  3. Read trailing CRLF
  4. Repeat until chunk-size is 0
  5. 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-Length and Transfer-Encoding present = immediate rejection
  • Duplicate CL rejection: Multiple Content-Length headers = rejection
  • Whitespace CL rejection: Content-Length: 42 (trailing space) = rejection
  • TE validation: Only chunked is 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