netune_http1/lib.rs
1//! A client-side HTTP/1.1 codec we own.
2//!
3//! ADR-0001 removes every third-party HTTP implementation from the production
4//! path because the request trace must map *bytes* to *frames* without a foreign
5//! buffer in between. This crate is that codec: it serializes a request, parses
6//! a response head, and decodes the body framing — nothing else. It holds no
7//! connection, no pool, no policy and no clock.
8//!
9//! # Scope, stated exactly
10//!
11//! Supported (RFC 9112, client side):
12//!
13//! - request line + header serialization with a length-delimited body;
14//! - response status line and header parsing (case-insensitive names, duplicate
15//! headers preserved, obsolete line folding rejected);
16//! - body framing: `Content-Length`, `Transfer-Encoding: chunked` (chunk
17//! extensions and trailers), close-delimited bodies, and the no-body cases
18//! (`HEAD`, `1xx`, `204`, `304`);
19//! - hard limits on head size, header count and chunk size, with typed errors
20//! and no panics.
21//!
22//! Deliberately out of scope: HTTP/2 and above, server-side parsing, content
23//! negotiation, redirects, compression, and connection pooling — those live in
24//! `netune` (policy) or are simply not needed.
25//!
26//! # Why `http` is still a dependency
27//!
28//! `http` is a *data-type* crate: `Method`, `StatusCode`, `HeaderMap`. It carries
29//! no parsing, no I/O and no policy, so keeping it does not put foreign
30//! behaviour in the measurement path. Everything that turns bytes into state is
31//! here.
32//!
33//! # Correctness posture
34//!
35//! The parser is accepted against a differential oracle (hyper) over a recorded
36//! corpus, fuzzed for panics, and bounded by [`Limits`]. See
37//! `tests/differential.rs`.
38
39#![cfg_attr(test, allow(clippy::unwrap_used, clippy::expect_used))]
40
41mod error;
42mod head;
43mod reader;
44mod writer;
45
46pub use error::HttpError;
47pub use head::{BodyKind, RequestHead, ResponseHead};
48pub use reader::{Http1Reader, Limits};
49pub use writer::write_request;