Expand description
HTTP/1.1 wire format — hand-rolled parsers and writers over plain byte
buffers. No hyper, no allocations beyond the owned result. The server half
is parse_request + serialize_response; the client half is its exact
mirror, serialize_request + parse_response — same error taxonomy,
same limits, same ParseError::Incomplete retry contract.
Scope (v1, deliberately bounded — documented so callers know the edges):
- Methods: any token (GET/POST/… are not restricted).
- Bodies: framed by
Content-Lengthonly.Transfer-Encoding: chunkedis rejected (ParseError::UnsupportedTransferEncoding) rather than silently mishandled. - Header names are normalized to lowercase on parse so lookups are case-insensitive (HTTP header names are case-insensitive by RFC 7230).
- Connection reuse: the SERVER speaks HTTP/1.1 persistent connections —
request_wants_keep_aliveis the one law both execution tiers apply (keep-alive unless the client’sConnectionheader listsclose), andserialize_response_connemits the matchingConnection:header.serialize_responseremains the one-shot (Connection: close) form, and the CLIENT half (serialize_request) still requests one-shot exchanges — a deliberate v1 client scope. - Sizes are bounded:
MAX_BODYcaps bodies (requests and responses alike),MAX_HEADERScaps the header block, so a malicious peer cannot exhaust memory. - Framing symmetry: both writers own the framing headers (an accurate
Content-Lengthcomputed from the body,Connection: close, neverTransfer-Encoding), so neither parser needs read-to-end-of-input framing — a missingContent-Lengthalways means an empty body, and torn input is alwaysParseError::Incomplete, never a guess at EOF.
serialize_response always emits an accurate Content-Length (computed
from the body) and Connection: close, and omits Date / other volatile
headers, so a response is a pure function of the handler’s output — which
is what lets the cross-tier differential assert byte-for-byte equality.
serialize_request obeys the same law on the client side.
Structs§
- Http
Request - A parsed HTTP request.
pathandqueryvalues are percent-decoded; header keys are lowercased.bodyis the raw bytes (a LOGOSRequest.body: Textis derived from this at the interpreter/AOT bridge). - Http
Response - A response to serialize.
statusis the numeric code;headersare written verbatim (exceptContent-Length/Connection/Transfer-Encoding, which the writer owns);bodyis raw bytes.
Enums§
- Parse
Error - Why a byte buffer could not be parsed into a complete request.
Constants§
- MAX_
BODY - Largest request body accepted, in bytes. Requests declaring a larger
Content-Lengthare rejected withParseError::BodyTooLarge. - MAX_
HEADERS - Largest header block (request line + headers, up to the blank line) accepted.
Functions§
- parse_
request - Parse a complete HTTP/1.1 request from
bytes. - parse_
request_ consuming parse_requestplus the number of bytes the request occupied — the keep-alive keystone: a persistent connection drains exactlyconsumedbytes and keeps the remainder (a pipelined next request) buffered.- parse_
response - Parse a complete HTTP/1.1 response from
bytes— the client-side mirror ofparse_request: sameParseError::Incompleteretry contract, sameMAX_BODY/MAX_HEADERScaps, same lowercased header keys, sameTransfer-Encodingrejection. - request_
wants_ keep_ alive - Whether the server should keep the connection open after answering
req— THE ONE keep-alive law both execution tiers (the interpreter’s serve loop and the AOTserve_on) apply, so theirConnection:responses can never drift: HTTP/1.1 connections persist unless the client’sConnectionheader token list containsclose(case-insensitive). - response_
header_ allowed - Whether a handler-supplied response header may pass to the wire — THE ONE
law both execution tiers (the interpreter bridge and AOT-emitted code) apply
before merging a LOGOS
Response.headersmap, so they can never drift: the name must be non-empty, must not be writer-owned framing or hop-by-hop (connection,content-length,transfer-encoding,keep-alive,upgrade), must not becontent-type(theResponse.contentTypefield is authoritative), and neither name nor value may contain CR, LF, or NUL (response splitting). The typed surface (withHeaderinhttp.lg) rejects these with anErrup front; this filter is the defense-in-depth for maps poked directly. - safe_
content_ type - The
Content-Typeactually emitted for a handler’scontentTypefield: the field verbatim when it is wire-safe, else thetext/plaindefault — so a CR/LF smuggled intocontentTypecan never split the response. Both execution tiers route the field through this, keeping them byte-identical. - serialize_
request - Serialize a request to bytes: request line (method, percent-encoded path and
query,
HTTP/1.1), the request’s headers (minus the writer-owned framing ones), an accurateContent-Length,Connection: close, the blank line, then the body — the exact client-side mirror ofserialize_response. - serialize_
response - Serialize a response to bytes: status line, the response’s headers (minus the
writer-owned ones), an accurate
Content-Length,Connection: close, the blank line, then the body — the one-shot form ofserialize_response_conn. - serialize_
response_ conn - Serialize a response with an explicit connection disposition: the writer
owns the
Connection:header (keep-aliveto hold the connection open for the next request,closeto end it) exactly as it ownsContent-Length— a handler can never desync framing or force persistence.