Skip to main content

Crate http_net

Crate http_net 

Source
Expand description

§http_net

An HTTP/1.1 engine that does no I/O itself. Feed it the bytes a socket delivered; it hands back requests (or responses) as borrowed views of those bytes, decodes their bodies, and serializes what you send back. The caller owns sockets, threads, and timers, so the same core runs under a blocking loop, an event loop, or a test that never opens a socket.

Parsing follows RFC 9112 strictly. Messages that recipients could disagree about are refused rather than repaired: conflicting Content-Length / Transfer-Encoding, duplicate Content-Length, obsolete line folding, bare CR or LF, whitespace before a colon, and control characters in field values each have their own HttpError. Every buffer is bounded by Limits, and each limit is checked before the bytes it governs are buffered.

§Tier 1: serve and fetch (blocking, std)

use http_net::{blocking, Response};

let server = blocking::Server::bind("127.0.0.1:0")?;
let addr = server.local_addr();
let stop = server.shutdown_handle();
let t = std::thread::spawn(move || server.serve(|req, _body| Response::text(200, req.path())));

let resp = blocking::get(&format!("http://{addr}/hi"))?;
assert_eq!(resp.text(), Some("/hi"));

stop.shutdown();
t.join().unwrap()?;

§Tier 2: the sans-IO connection

use http_net::{Response, ServerConn, ServerEvent};

let mut conn = ServerConn::new();
let mut out = Vec::new();
let _ = conn.feed(b"GET /status HTTP/1.1\r\nHost: localhost\r\n\r\n");
loop {
    match conn.poll()? {
        ServerEvent::Request(req) => assert_eq!(req.path(), "/status"),
        ServerEvent::Body(_) => {}
        ServerEvent::RequestEnd => conn.respond(&Response::text(200, "up"), &mut out)?,
        _ => break, // NeedInput: read more from the socket
    }
}
assert!(out.starts_with(b"HTTP/1.1 200 OK\r\n"));

ClientConn is the mirror image for the client side, and the blocking module shows how either is driven over std::net.

§Protocol upgrades

A request with Connection: upgrade and an Upgrade field offering a protocol other than h2c reports RequestHead::is_upgrade. Answering it with Response::switching_protocols naming an offered protocol moves the connection to ServerEvent::Upgraded, after which ServerConn::remaining_input holds any bytes of the new protocol that arrived with the request. This is the hand-off point for a WebSocket engine such as ws-net.

§Feature flags

FeatureDefaultDescription
stdyesThe blocking adapter over std::net. Without it the crate is no_std and needs only alloc (built in CI for thumbv7em-none-eabihf).

§Credentials in Debug output

Every Debug implementation in the crate prints the values of authorization, proxy-authorization, cookie, and set-cookie as <redacted N bytes>, so logging a request with {:?} never leaks a session cookie or a bearer token. The accessors return the real values.

Re-exports§

pub use status::StatusClass;
pub use status::reason_phrase;
pub use status::status_allows_body;
pub use status::status_class;

Modules§

blockingstd
A small blocking adapter over std::net: the Tier-1 path.
status
The HTTP status code registry: a named constant for every registered code, the canonical reason phrases, and status classes.

Structs§

Asked
What the request asked for, which decides how its response is framed (RFC 9112 section 6.3): a response to HEAD has no body whatever its fields say, and a 2xx to CONNECT turns the connection into a tunnel. The input to parse_response_head.
ChunkedDecoder
Decodes a chunked body (RFC 9112 section 7.1) from input the caller owns, with the exact grammar and budgets of the connections. Nothing is allocated.
ClientConn
The client side of one HTTP/1.1 connection: a sans-IO state machine.
ClientLeniency
Opt-in tolerances for responses a strict client would refuse. All are off by default; requests are never parsed leniently.
DateCache
A Date value reformatted at most once per second.
FieldSpan
One field line of a head: the name’s span and the value’s span (the value without surrounding whitespace), as offsets into the head bytes.
HeadFacts
The interpreted facts of a request head (method, version, framing, keep-alive, upgrade and expectation flags, target form, and the spans of the host and of the target’s parts), so a view can be rebuilt from copied bytes without parsing them again. Returned by RequestHead::copy_into, taken by OwnedRequestHead::from_parts.
HeaderValues
Iterator over the values of every field with one name, in arrival order: what RequestHead::header_all and ResponseHead::header_all return. Each Set-Cookie, for example, is its own field and its own item; nothing is comma-joined.
Headers
Iterator over a head’s fields as (name, value) pairs, in arrival order.
HttpDate
A formatted Date value: an IMF-fixdate such as Sun, 06 Nov 1994 08:49:37 GMT (always 29 bytes).
Limits
The budgets a connection enforces on incoming messages.
ListElements
Iterator over the elements of a list field (#rule) across every line with one name: what RequestHead::header_list, ResponseHead::header_list, RequestHead::upgrade_protocols, and RequestHead::connection_options return. Elements are trimmed of whitespace, empty ones are skipped, and a comma inside a quoted string does not split an element.
MethodSet
A set of methods: one bit per Method, so a membership check is one AND. For routers and for the Allow field of a 405 response.
OwnedRequestHead
A request head that owns its bytes and spans: from RequestHead::to_owned, or rebuilt from a passport’s parts with from_parts. Debug shows the head the way RequestHead does, credential values redacted.
ParsedRequest
A request head from parse_request_head, borrowing the input and the caller’s field array.
ParsedResponse
A response head from parse_response_head.
RawHead
The bytes of a head and the spans of its parts, all relative to bytes: what RequestHead::raw and ResponseHead::raw return.
Request
A request for a ClientConn to send.
RequestHead
A parsed request head, borrowed from the connection’s buffer.
Response
A response for a ServerConn to send.
ResponseHead
A parsed response head, borrowed from the client connection’s buffer.
ResponseHeadRef
A response head described with borrowed data, for ServerConn::write_head: nothing is copied into an owned builder and nothing is allocated.
ServerConn
The server side of one HTTP/1.1 connection: a sans-IO state machine.
Span
A byte range of a message head: start..end, as offsets into RawHead::bytes (or into the input of a stateless parser).

Enums§

BodyFraming
How a message’s body is delimited.
BodyPlan
What the caller must do after ServerConn::write_head.
ChunkStep
One step of ChunkedDecoder::decode, with explicit byte accounting so a caller can decode in place in its own buffer. Offsets are relative to the input of that call.
ClientEvent
What a ClientConn has for the caller after poll.
HttpError
Why a message was refused, or why a call was out of order.
Method
The request method.
OutgoingBody
How the body of a response written with ServerConn::write_head is supplied.
Parsed
The result of a stateless parse: a complete head and how many input bytes it took, or Partial when the input ends before the head does.
Progress
The phase of a connection, for drivers that run header-read, request, and response deadlines: what ServerConn::progress and ClientConn::progress report.
ServerEvent
What a ServerConn has for the caller after poll.
TargetForm
The form of a request target (RFC 9112 section 3.2).
Version
The HTTP version of a message.

Constants§

VERSION
The crate version, as published (CARGO_PKG_VERSION).

Traits§

Output
Where serialized bytes go.

Functions§

is_h2_preface
Whether input starts with the HTTP/2 connection preface: Some(true) when the first 24 bytes are the preface, Some(false) as soon as a byte differs from it, and None while input is a shorter, so far matching prefix (read more to decide). At most 24 compares.
is_hop_by_hop
Whether a field named name is hop-by-hop: one of connection, keep-alive, proxy-connection, te, transfer-encoding, upgrade, trailer, or any name the message’s Connection field lists (RFC 9110 section 7.6.1). A proxy removes these before forwarding a message. Names compare ASCII case-insensitively. For a request, pass RequestHead::connection_options as connection_options; for a response, pass ResponseHead::header_list("connection") (a ResponseHead has no connection_options).
parse_request_head
Parses one request head from the start of input, with the rules and budgets of ServerConn (the same scanner and interpretation code), writing the field records into fields. Allocates nothing. Unlike ServerConn, it does not check for the HTTP/2 connection preface first; call is_h2_preface for that.
parse_response_head
Parses one response head from the start of input with the rules of ClientConn, framed by what the request asked (a HEAD request’s response has no body; a 2xx to CONNECT is a tunnel). Interim (1xx) heads are returned like any other; check ResponseHead::is_informational and parse the next head after len. No ClientLeniency applies, so obsolete line folding is always HttpError::ObsFold. Allocates nothing.