barehttp
Blocking HTTP/1.1 client for no_std + alloc. Cleartext HTTP; no async.
Design notes: philosophy.md.
MSRV: Rust 1.90 (rust-version in Cargo.toml; const APIs, ruzstd, and gungraun/bincode-next when building benches).
https:// needs [config::Config::assume_tls_socket] and a [BlockingSocket] that terminates TLS.
[OsBlockingSocket] is TCP only. Pairing it with assume_tls_socket returns
[Error::TlsNotConfigured].
Naming
Primary names:
| Role | Primary | Compatibility alias |
|---|---|---|
| Client | [HttpClient] |
[Agent] (= HttpClient<OsBlockingSocket, OsDnsResolver>) |
| Request builder | [ClientRequestBuilder] |
[RequestBuilder] (same OS adapters) |
Cookie store (cookie-jar) |
[cookie_jar::CookieStore] |
[cookie_jar::CookieJar] |
| Status / body | [Response::status_code], [Response::body] |
deprecated [Response::status] / [Response::as_bytes] |
[Agent] / [RequestBuilder] / [cookie_jar::CookieJar] are documented ureq-like synonyms and are not deprecated. Prefer the primary names in new code. README and examples use primaries only.
[agent] builds a default-OS [HttpClient]. Free functions ([get], [post], …) return a builder; finish with [ClientRequestBuilder::call] or [ClientRequestBuilder::send]:
#
Module layout
Hot types live at the crate root (HttpClient, Response, Error, Headers, …).
Optional / larger surfaces stay in modules: [config], [request_builder], and
(feature-gated) [cookie_jar] / [gzip]. The half-nesting is intentional.
Intentional limits
- Buffered response bodies (no streaming
Readbody API). - Blocking I/O only (no async runtime).
- Public body accessors use
&[u8]/Vec<u8>/Stringonly (core/alloc).
Features
- Custom [
BlockingSocket] / [DnsResolver] (connectgets the hostname for SNI) - Connection pooling (
Config::max_idle_per_hostdefault 3;0disables;max_idle_agedefault 15s) - Response body size limit (
Config::max_response_body_size, default ~10 MiB) - Optional Cargo features:
gzipexposesbarehttp::gzip(hand-rolled RFC 1951/1952);zstdis Accept-Encoding + decode only;cookie-jargates the cookie module - Runtime deps (always on, kept out of the public API):
bytes(internal body / wire buffers),phf(well-known header name map),compact_str(SSO header strings),hashbrown(header side-index / pool). Platform:libc/windows-sys. - Request builder:
.form/.bodythen.call(), or.send(bytes); per-request.timeout_read/.timeout_write/.timeout_connect
See CHANGELOG.md for release notes.
Examples
All examples use cleartext HTTP (http:// only):
cargo run --example basic # GET http://example.com
cargo run --example agent # shared client, headers + query
cargo run --example custom_adapters # logging DnsResolver + BlockingSocket over the OS stack
cargo run --example gzip --features gzip # http://httpbingo.org/gzip
cargo run --example cookies --features cookie-jar # httpbingo/postman-echo cookie endpoints
TLS / HTTPS
barehttp does not implement TLS. For https://:
- Use a [
BlockingSocket] whoseconnect/ read / write speak TLS (or wrap one that does).connectreceives the URI hostname for SNI. - Set
assume_tls_socketon [config::Config] so the client acceptshttps. Without that flag you get [Error::TlsNotConfigured].
use Config;
use HttpClient;
let config = builder
.assume_tls_socket
.build;
// Pair with a TLS-capable BlockingSocket. OsBlockingSocket is cleartext
// and rejects this config.
let client = with_adapters;
Config
use Config;
use HttpClient;
use Duration;
#
Custom adapters
use Config;
use ;
let client: =
with_adapters;
See examples/custom_adapters.rs for logging wrappers around [OsDnsResolver] / [OsBlockingSocket].
Testing
Use cargo-nextest:
CI runs nextest on push and pull requests. Details in CONTRIBUTING.md; fuzz targets in fuzz/README.md.
License
MIT OR Apache-2.0. Changes: CHANGELOG.md.