httparse

A tiny, safe, zero-copy push parser for the HTTP/1.x protocol in Rust

Library
Cargo
v1.10.1
710stars
MIT OR Apache-2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
53/100Fair
Development Activity36
Maintenance28
Community60
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
85/100Excellent
Architecture88
Code Quality90
Innovation85
Learning Curve75

httparse is a low-level, zero-copy HTTP/1.x parser for Rust. Rather than owning a socket or buffer, it works as a push parser: callers feed it a byte slice and it fills in Request or Response structs (method, URI/status, version, and headers) that borrow directly from that slice, with no allocation and no copying. Unsafe code is deliberately confined to a small, invariant-checked core so the public API stays safe to use.

The parser is SIMD-accelerated on x86/x86_64 (AVX2, SSE4.2) and aarch64 (NEON), with runtime feature detection that picks the fastest available path and falls back to a portable SWAR (SIMD-within-a-register) implementation elsewhere, including no_std targets. Because of its speed and minimal footprint, httparse is the HTTP/1.x parsing layer underneath widely used crates such as hyper, making it one of the most heavily exercised pieces of low-level networking code in the Rust ecosystem.

What You Get

  • Request and Response structs that parse method/URI/version or status/reason plus headers directly out of a borrowed byte slice, with zero copying
  • SIMD-accelerated matching (AVX2, SSE4.2, NEON) with automatic runtime feature detection and a portable SWAR fallback for other targets
  • A ParserConfig builder for opting into lenient parsing behaviors (extra spaces around delimiters, obsolete multiline headers, spaces before header names)
  • no_std support via the optional std feature, so the parser can run in embedded or kernel-adjacent contexts
  • Standalone helpers (parse_method, parse_uri, parse_version, parse_headers, parse_chunk_size) for parsing pieces of the protocol independently
  • A Status<T> enum (Complete/Partial) that makes incremental parsing over streamed, not-yet-complete buffers explicit and type-safe

Common Use Cases

  • Parsing incoming request lines and headers inside a custom or high-performance HTTP server
  • Parsing response status lines and headers inside an HTTP client implementation
  • Decoding chunked-transfer-encoding chunk sizes with parse_chunk_size
  • Embedding HTTP/1.x parsing in no_std environments such as firmware, unikernels, or WASM modules where the standard library isn’t available

Under The Hood

Architecture — httparse is organized as a push parser: the caller owns the socket, the read loop, and the byte buffer, and simply calls Request::parse or Response::parse (or the config-driven ParserConfig::parse_request/parse_response) each time more bytes arrive. Internally, src/iter.rs defines a Bytes cursor that wraps a slice and exposes bounds-checked-once, then-unchecked advancement primitives used throughout src/lib.rs’s hand-written parsing routines for the method, URI, version, status, and header name/value tokens. src/macros.rs provides small helpers (byte_map!, next!, expect!) used to build lookup tables and drive the character-by-character state machine. The header/URI/value matching hot paths are delegated to src/simd/, which picks an implementation (avx2.rs, sse42.rs, neon.rs, or the portable swar.rs) at compile time or, on x86/x86_64 without fixed target features, via src/simd/runtime.rs’s is_x86_feature_detected!-based runtime dispatch cached in an atomic.

Tech Stack — Pure Rust, edition 2021, minimum supported Rust version 1.59, with zero runtime dependencies; criterion and rand are dev-dependencies used only for benchmarking (benches/parse.rs, harness = false, LTO + single codegen unit in the bench profile). The crate is #![cfg_attr(not(any(test, feature = "std")), no_std)], gated behind a default-on std Cargo feature, so consumers can opt out of std entirely. A fuzz/ directory holds cargo-fuzz targets for continuous fuzzing of the parser against malformed input.

Code Quality — The crate denies missing_docs and clippy::undocumented_unsafe_blocks at the crate level, so every unsafe block carries an explicit safety-invariant comment and every public item is documented. Testing is thorough: 53 inline #[test] functions in src/lib.rs cover request/response parsing edge cases (partial buffers, header limits, obsolete line folding, chunk sizes), plus a dedicated tests/uri.rs with roughly 3,700 lines exercising URI-token edge cases, on top of the fuzz targets for adversarial input. Errors are modeled as a small, exhaustive Error enum (HeaderName, HeaderValue, NewLine, Status, Token, TooManyHeaders, Version) rather than a generic failure type, which keeps failure modes explicit at call sites.

API Design — The public surface is small and consistent: construct a Request/Response with a caller-provided header buffer, call .parse(buf), and match on Status::Complete(usize) vs Status::Partial. ParserConfig uses a chainable builder for the handful of leniency toggles instead of overloading parse with flags, and EMPTY_HEADER plus Header { name, value } keep header buffer initialization trivial. Because the parser borrows from the input slice instead of allocating, the API pushes lifetime management to the caller in exchange for zero-copy performance — a deliberate, well-documented trade-off rather than an accident of implementation.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search