Overview of attohttpc
masterhttp, url, and encoding_rs.repository·master·Indexed 43 days ago
https://github.com/sbstp/attohttpcA small, lightweight, and synchronous HTTP/1.1 client for Rust designed for simplicity and small binary sizes. It avoids the asynchronous stack and provides modular functionality via feature flags for JSON serialization, TLS (native-tls or rustls), compression, and multipart forms. Version 0.31.0.
http, url, and encoding_rs.The BodyKind enum describes how the request body is transmitted. This information is used to determine if the body has a known length or requires chunked encoding.
Empty: No body content.KnownLength(u64): A body with a specific, pre-determined size.Chunked: A body transferred using chunked encoding (common for streaming data).A Session is a container for settings that are applied to every request created from it. This allows you to define common headers, timeouts, proxy settings, and TLS configurations once and reuse them across multiple requests.
Session can be cloned cheaply and sent to other threads because it uses std::sync::Arc internally.
To use a session, create a new one with Session::new() and then use its HTTP method helpers (like .get(), .post(), etc.) to generate RequestBuilder instances that inherit the session's configuration.
use attohttpc::Session;
use std::time::Duration;
let mut session = Session::new();
// Configure the session
session.header("Authorization", "Bearer my_token");
session.connect_timeout(Duration::from_secs(5));
// Create requests using the session's settings
let response = session.get("https://api.example.com/data")
.send()?
.text()?;The Body trait is the core abstraction for request payloads in attohttpc. Any type implementing Body can be used as a request body. The trait is designed to be rewindable, meaning the write method can be called multiple times (e.g., during HTTP redirects).
Key methods:
kind(): Returns a BodyKind indicating if the length is known or if it is chunked.write<W: Write>(&mut self, writer: W): Writes the body content into the provided writer.content_type(): Returns an optional String representing the MIME type of the body.The Multipart struct is the result of calling MultipartBuilder::build(). It implements the Body trait, meaning it can be passed directly into attohttpc request methods.
When used as a body:
Content-Type header is automatically set to multipart/form-data including the required boundary parameter.Chunked encoding.// Assuming 'client' is an attohttpc client
let body = MultipartBuilder::new()
.with_text("field", "value")
.build()?;
let response = client.post("https://example.com/upload")
.body(body)
.send()?;attohttpc is modular. You can enable or disable specific capabilities using Cargo feature flags to keep your binary size small.
compress (default): Decompresses response bodies using miniz_oxide.compress-zlib: Uses zlib instead of miniz_oxide.compress-zlib-ng: Uses zlib-ng instead of miniz_oxide.tls-native (default): Uses the native-tls crate.tls-native-vendored: Activates the vendored feature of native-tls.tls-rustls-webpki-roots: Uses rustls with Web PKI roots.tls-rustls-native-roots: Uses rustls with root certificates from the rustls-native-certs crate.json: Enables serde serialization and deserialization.charsets: Supports decoding text encodings beyond UTF-8.form: Supports URL-encoded forms (excludes multipart).multipart-form: Supports multipart forms (excludes URL encoding).attohttpc uses feature flags to keep the crate small. You can enable specific functionality by adding them to your Cargo.toml file.
Example:
attohttpc = { version = "...", features = ["json", "form", "multipart-form"] }attohttpc = { version = "...", features = ["json", "form", ...] }attohttpc is a lightweight, synchronous HTTP client for Rust. It is designed for projects where performance is not the absolute priority or where HTTP is not the main purpose of the application. It avoids the asynchronous stack to remain small and efficient.
To perform a POST request with a JSON body, headers, and query parameters, use the following pattern:
# #[cfg(feature = "json")]
# use serde_json::json;
# #[cfg(feature = "json")]
# fn main() -> attohttpc::Result {
let obj = json!({
"hello": "world",
});
let resp = attohttpc::post("https://my-api.org/do/something")
.header("X-My-Header", "foo") // set a header for the request
.param("qux", "baz") // set a query parameter
.json(&obj)? // set the request body (json feature required)
.send()?; // send the request
// Check if the status is a 2XX code.
if resp.is_success() {
// Consume the response body as text and print it.
println!("{}", resp.text()?);
}
# Ok(())
# }
# #[cfg(not(feature = "json"))]
# fn main() {}let obj = json!({
"hello": "world",
});
let resp = attohttpc::post("https://my-api.org/do/something")
.header("X-My-Header", "foo")
.param("qux", "baz")
.json(&obj)?
.send()?;
if resp.is_success() {
println!("{}", resp.text()?);
}You can perform a POST request with a JSON body and deserialize the response using the .json() method. This requires the json feature flag to be enabled.
let resp = attohttpc::post("https://my-api.com/do/something")
.json(&request)?
.send()?;
if resp.is_success() {
let response = resp.json()?;
// ...
}let resp = attohttpc::post("https://my-api.com/do/something").json(&request)?.send()?;
if resp.is_success() {
let response = resp.json()?;
// ...
}The current feature set includes:
native-tls and rustls).Transfer-Encoding: chunked support.serde/json support.HTTP_PROXY, HTTPS_PROXY, and NO_PROXY environment variables.The ProxySettings::from_env() method initializes proxy settings following standard curl/Unix conventions. It looks for the following environment variables (case-insensitive):
ALL_PROXY: A fallback proxy for all schemes.HTTP_PROXY: Proxy for http requests. Takes precedence over ALL_PROXY for HTTP.HTTPS_PROXY: Proxy for https requests. Takes precedence over ALL_PROXY for HTTPS.NO_PROXY: A comma-separated list of hostnames or domains that should bypass the proxy. If set to *, all proxies are disabled.Note: HTTP_PROXY or HTTPS_PROXY will override the values set by ALL_PROXY for their respective schemes.
use attohttpc::request::proxy::ProxySettings;
// Loads settings from ALL_PROXY, HTTP_PROXY, HTTPS_PROXY, and NO_PROXY
let settings = ProxySettings::from_env();Adjust request behavior and connection settings:
max_redirections(n): Sets the maximum number of redirections (default: 5).follow_redirects(bool): Enables/disables following 3xx redirects (default: true).connect_timeout(duration): Sets the connection timeout (default: 30s).read_timeout(duration): Sets the read timeout (default: 30s).timeout(duration): Sets a timeout for the entire request after connection is established.max_headers(n): Sets the maximum number of headers accepted in responses (default: 100).proxy_settings(settings): Configures proxy settings.allow_compression(bool): (Requires flate2 feature) Signals that the request accepts compression.danger_accept_invalid_certs(bool): (Danger) Accepts any TLS certificate (valid or not).danger_accept_invalid_hostnames(bool): (Danger) Accepts TLS certificates that do not match the hostname.use std::time::Duration;
builder
.connect_timeout(Duration::from_secs(5))
.read_timeout(Duration::from_secs(10))
.follow_redirects(true)
.max_redirections(3);