oxihttp-client — Pure-Rust HTTP client for the OxiHTTP stack

oxihttp-client is the HTTP client of the OxiHTTP stack. It provides a fluent, reqwest-style API over a pooled connection layer: connection pooling, redirect following, retry with exponential backoff, per-request timeouts, automatic cookie management (RFC 6265), a lightweight middleware chain, custom DNS resolution, HTTP/HTTPS CONNECT and SOCKS5 proxies, optional transparent decompression, and optional HTTP/3.
The client builds on hyper and hyper-util's legacy pooled client for the HTTP/1.1 and HTTP/2 transports; all shared types (OxiHttpError, Body, cookies, multipart, forms) come from oxihttp-core. TLS is optional and Pure Rust via oxitls + rustls/tokio-rustls (no OpenSSL); decompression is Pure Rust via oxiarc-deflate; HTTP/3 is Pure Rust via oxiquic-h3. The crate is #![forbid(unsafe_code)].
Installation
[dependencies]
oxihttp-client = "0.1.0"
oxihttp-client = { version = "0.1.0", features = ["tls"] }
oxihttp-client = { version = "0.1.0", features = ["tls", "decompression", "socks", "h3"] }
Quick Start
use oxihttp_client::Client;
# async fn example() -> Result<(), oxihttp_core::OxiHttpError> {
let client = Client::builder().build()?;
let resp = client
.get("http://example.com")?
.header("accept", "application/json")?
.send()
.await?;
assert_eq!(resp.status(), http::StatusCode::OK);
let body = resp.body_text().await?;
println!("{body}");
# Ok(())
# }
POST JSON and deserialize the response
use oxihttp_client::Client;
# async fn example() -> Result<(), oxihttp_core::OxiHttpError> {
#[derive(serde::Serialize)]
struct CreateUser { name: String }
#[derive(serde::Deserialize)]
struct User { id: u64 }
let client = Client::builder().build()?;
let user: User = client
.post_json("http://example.com/users", &CreateUser { name: "Alice".into() })
.await?;
println!("created id={}", user.id);
# Ok(())
# }
API Overview
Client<C> — the HTTP client
Cloneable and cheap to share. The default Client<HttpConnector> is HTTP-only; type aliases provide TLS- and resolver-backed variants (see below).
| Method |
Description |
Client::builder() |
Start a ClientBuilder (only on the default HttpConnector variant, for ergonomic inference) |
get / post / put / delete / patch / head (url) |
Build a RequestBuilder<C> for the method |
execute(http::Request<Full<Bytes>>) |
Send a pre-built request |
get_bytes(url) |
GET → error_for_status() → body Bytes |
get_json::<T>(url) |
GET → deserialize JSON body |
post_json::<T, R>(url, &body) |
POST JSON → deserialize JSON response |
retry_policy() / connect_timeout() / read_timeout() |
Inspect configured settings |
Client type aliases
| Alias |
Built via |
Notes |
Client<HttpConnector> (default) |
ClientBuilder::build() |
Plain HTTP |
HttpsClient (feature tls) |
ClientBuilder::build_https() |
http:// + https:// |
ResolverClient |
ClientBuilder::build_with_resolver() |
Custom DNS, plain HTTP |
ResolverHttpsClient (feature tls) |
ClientBuilder::build_https_with_resolver() |
Custom DNS + TLS |
HttpsClient extras (feature tls)
| Method |
Description |
with_request_tls_config(RequestTlsConfig) |
Derive a new HttpsClient (own pool) with overridden TLS trust — per-endpoint certificate pinning |
ClientBuilder
Construct with Client::builder() or ClientBuilder::new(). All setters are chainable.
| Method |
Description |
pool_max_idle_per_host(n) |
Max idle pooled connections per host |
pool_idle_timeout(Duration) |
Idle connection timeout |
connect_timeout(Duration) |
TCP connect timeout |
read_timeout(Duration) |
Response read timeout |
redirect_policy(RedirectPolicy) |
Redirect behaviour |
retry_policy(RetryPolicy) |
Retry behaviour |
default_headers(HeaderMap) |
Headers added to every request |
user_agent(impl Into<String>) |
Set the User-Agent |
with_decompression(bool) |
Toggle transparent decompression (needs decompression) |
with_middleware(M) / with_layer(M) |
Append a ClientMiddleware |
with_cookie_jar(Arc<Mutex<CookieJar>>) / with_new_cookie_jar() |
Enable RFC 6265 cookie management |
with_http2_settings(Http2Settings) |
HTTP/2 tuning |
with_tcp_nodelay(bool) / with_tcp_keepalive(Duration) |
TCP socket tuning |
with_resolver(R) |
Set a custom DnsResolver |
with_http_proxy(Uri) |
Route via HTTP CONNECT proxy |
with_socks5_proxy(Uri) (feature socks) |
Route via SOCKS5 proxy |
| Build methods |
|
build() |
Plain HTTP Client |
build_https() (tls) |
HttpsClient |
build_with_resolver() |
ResolverClient |
build_https_with_resolver() (tls) |
ResolverHttpsClient |
build_proxy() |
Client<ProxyConnector> (HTTP CONNECT) |
build_proxy_https() (tls) |
HTTPS over HTTP CONNECT |
build_socks5_proxy() (socks) |
Client<Socks5Connector> |
build_socks5_proxy_https() (tls + socks) |
HTTPS over SOCKS5 |
TLS setters (feature tls) |
|
with_tls() / with_webpki_roots() |
Trust the Mozilla CA bundle |
with_trusted_cert_der(Vec<u8>) |
Add a DER-encoded trusted CA |
with_alpn(&[&str]) |
Advertise ALPN protocols |
with_danger_accept_invalid_certs() |
Testing only — disable cert verification |
with_key_log_file(PathBuf) |
Write SSLKEYLOGFILE-format secrets (dev only) |
with_early_data() |
Enable TLS 1.3 0-RTT early data (idempotent requests only) |
RequestBuilder<C> — per-request builder
Returned by Client::get() etc. Terminal method is send().
| Method |
Description |
header(key, value) |
Add a header |
headers(HeaderMap) |
Merge headers |
bearer_token(token) |
Set Authorization: Bearer … |
basic_auth(user, Option<pass>) |
Set Authorization: Basic … |
body(impl Into<Bytes>) |
Raw request body |
json(&T) |
JSON body + Content-Type: application/json |
form(&FormBody) |
URL-encoded form body |
multipart(MultipartBuilder) |
multipart/form-data body (auto Content-Type unless preset) |
timeout(Duration) |
Per-request timeout |
send() -> Result<Response> |
Execute (honours redirects, retries, middleware, cookies) |
Response
| Method |
Description |
status() |
StatusCode |
headers() |
&HeaderMap |
version() |
http::Version |
content_length() |
Option<u64> |
content_type() |
Content-Type as &str |
cookies() |
Parse all Set-Cookie into Vec<oxihttp_core::Cookie> |
error_for_status() |
Err on 4xx/5xx, else Ok(self) |
body_bytes() |
Consume body → Bytes (auto-decompress if enabled) |
body_text() |
Consume body → String |
body_json::<T>() |
Consume body → deserialized T |
body_stream() |
Consume body → BodyStream |
BodyStream implements futures_core::Stream<Item = Result<Bytes, OxiHttpError>>.
RedirectPolicy (redirect module)
| Variant / item |
Description |
None |
Never follow; return the redirect response |
Limited(usize) |
Follow up to n (the Default is Limited(10)) |
All |
Follow all redirects |
max_redirects() / is_none() |
Inspection |
Free functions: is_redirect_status(StatusCode), redirect_method(StatusCode, &Method) (301–303 demote POST→GET), should_preserve_body(StatusCode) (307/308 only).
RetryPolicy (retry module)
Public fields: max_retries, backoff_base, backoff_max, retryable_status_codes, retry_on_connection_error, retry_on_timeout. Default retries 3 times.
| Method |
Description |
new(max_retries) |
Defaults: 100 ms base, 30 s cap, retry 429/500/502/503/504 |
with_backoff_base / with_backoff_max |
Tune backoff |
with_retryable_status_codes(set) / add_retryable_status(code) |
Customise retryable statuses |
with_retry_on_connection_error(bool) / with_retry_on_timeout(bool) |
Toggle error retries |
should_retry_status(u16) |
Predicate |
backoff_delay(attempt) |
Exponential delay (capped) |
Http2Settings (client_builder module)
A Default struct of optional HTTP/2 knobs: initial_stream_window_size, initial_connection_window_size, adaptive_window, keep_alive_interval, keep_alive_timeout, max_frame_size, max_concurrent_reset_streams, max_send_buf_size.
Middleware (middleware module)
| Item |
Description |
ClientMiddleware (trait) |
before_request(&RequestContext) + after_response(&ResponseContext) observers |
RequestContext<'a> |
method, uri, headers of the outgoing request |
ResponseContext |
Final status + elapsed duration |
LoggingMiddleware::new(name) |
Logs each request/response to stderr |
TimingMiddleware::new(Fn(Duration)) |
Invokes a callback with elapsed time |
Custom DNS (resolver module)
| Item |
Description |
DnsResolver (trait) |
resolve(&str) -> Future<Vec<SocketAddr>> |
GaiDnsResolver |
Default resolver via tokio::net::lookup_host |
BoxResolver, BoxResolverAddrs |
Public glue used by the resolver Client aliases |
Proxies (proxy module)
| Item |
Description |
ProxyKind |
HttpConnect(Uri) or Socks5(Uri) (feature socks) |
ProxyConnector |
Service<Uri> tunnelling via HTTP CONNECT (+ optional Proxy-Authorization) |
Socks5Connector (feature socks) |
Service<Uri> SOCKS5 (RFC 1928/1929), forwards DNS names to the proxy |
TLS types (feature tls)
| Item |
Module |
Description |
OxiHttpsConnector<H> |
connector |
Upgrades to TLS for https://, passes through http:// |
MaybeHttpsStream<T> |
connector |
Plain-or-TLS stream (Http / Https) |
RequestTlsConfig |
request_config |
Per-request TLS trust override (trusted_cert_ders, accept_invalid_certs); new, with_trusted_cert, with_accept_invalid_certs |
HTTP/3 (feature h3, h3 module)
A thin wrapper over oxiquic-h3.
| Item |
Description |
H3ConnectionBuilder::new(server_name) |
Builder; with_tls_config(rustls::ClientConfig) then connect(SocketAddr) |
H3Connection |
get / post / head / put / delete / request(H3Request, Option<Bytes>) / close() |
H3Request, H3Response |
Re-exported from oxiquic-h3 |
Feature Flags
| Feature |
Default |
Description |
tls |
off |
HTTPS via oxitls + rustls/tokio-rustls (Pure Rust); enables HttpsClient, OxiHttpsConnector, RequestTlsConfig |
decompression |
off |
Transparent gzip/deflate decompression via oxiarc-deflate |
socks |
off |
SOCKS5 proxy support (Socks5Connector, ProxyKind::Socks5) |
h3 |
off |
HTTP/3 client via oxiquic-h3 (pulls in rustls) |
Error type
All fallible APIs return oxihttp_core::OxiHttpError. See the oxihttp-core README for the full variant table; the client most commonly produces Hyper, Io, Timeout, Redirect, Tls, Dns, ConnectionPool, Body, Json, InvalidHeader, InvalidUri, and (HTTP/3) H3.
Related crates
oxihttp — the unified facade re-exporting this client.
oxihttp-core — shared types (OxiHttpError, Body, cookies, multipart, forms).
oxihttp-server — the matching HTTP server.
License
Apache-2.0 — COOLJAPAN OU (Team Kitasan)