Overview
The HTTP client abstraction provides a runtime-agnostic interface for making HTTP requests. It’s primarily used for:
- Media uploads to WhatsApp servers
- Media downloads (with streaming support)
- Fetching metadata and authentication tokens
The client supports both buffered and streaming responses for efficient handling of large files.
HttpClient Trait
MaybeSendSync is Send + Sync on native targets and carries no bounds on wasm32. Custom HttpClient implementations backed by !Send browser fetch handles now compile on the wasm port. On native, Arc<dyn HttpClient> remains Send + Sync as before.
supports_upload_streaming / execute_upload were added in v0.6 to back Client::upload_stream. Both have safe defaults (returning false / an error), so existing custom HttpClient implementations keep compiling — implement them only if you want constant-memory uploads through your client. UreqHttpClient implements both. UploadBody is Box<dyn std::io::Read + Send>.
Methods
supports_streaming
Returns whether this HTTP client supports synchronous streaming downloads via execute_streaming. The default implementation returns false. When this returns false, download_to_writer automatically falls back to a buffered download using execute instead.
Returns:
true if execute_streaming is implemented (e.g., UreqHttpClient)
false (default) if streaming is not supported
execute
Executes an HTTP request and buffers the entire response body.
Parameters:
request: HttpRequest - The request to execute
Returns:
HttpResponse with buffered body on success
anyhow::Error on failure
Example:
execute_streaming
Executes an HTTP request and returns a streaming reader over the response body.
Important: This is a synchronous method that must be called from within tokio::task::spawn_blocking.
Parameters:
request: HttpRequest - The request to execute
Returns:
StreamingHttpResponse with streaming body reader
anyhow::Error on failure or if streaming is not supported
Example:
resource_report
Best-effort per-session footprint of this client: idle connection-pool buffers plus any in-flight download/media buffering the implementation can see. Defaulted to None (“not reported”) — a client that can introspect its pool overrides it.
Returns:
Some(HttpResourceReport) with any subset of pool_connections, pool_buffer_bytes, inflight_bytes filled in (each Option<u64>)
None (default) if the client doesn’t report
Feeds into Client::resource_report(). UreqHttpClient overrides this (below) with an estimate for its default agent’s idle pool; media downloads are a real transient-RAM source, so even a coarse estimate is worth reporting.
Data Structures
HttpRequest
Represents an HTTP request with headers and optional body.
Constructors
Builder Methods
HttpResponse
Represents an HTTP response with buffered body.
Methods
StreamingHttpResponse
Represents an HTTP response with streaming body reader.
Usage:
UreqHttpClient
The default HTTP client implementation using the ureq crate (v3.3) for synchronous HTTP requests.
Features
- Blocking I/O - Uses synchronous ureq, wrapped in
tokio::task::spawn_blocking
- Connection pooling - Shares a
ureq::Agent across requests for connection reuse
- Streaming support - Implements efficient streaming downloads
- Simple API - Minimal configuration required
- Thread-safe - Implements
Clone for easy sharing (cloning the Agent is cheap)
- TLS via rustls - Uses rustls for TLS, with optional
danger-skip-tls-verify for testing
Creating a client
with_agent
Creates a client with a pre-configured ureq::Agent. This lets you configure proxy support, custom TLS, timeouts, or any other agent-level settings externally.
This is the primary extension point for customizing HTTP behavior — for example, routing media uploads and downloads through a proxy, or using custom CA certificates.
Parameters:
agent - A pre-configured ureq::Agent
Example — proxy support:
See custom backends — proxy and custom TLS for a complete guide.
Usage Examples
Basic GET Request
POST request with body
Streaming Download
Internal Implementation
The UreqHttpClient wraps a shared ureq::Agent for connection pooling. All requests go through the agent rather than standalone ureq::get()/ureq::post() functions:
When the danger-skip-tls-verify feature is enabled, the agent is built with TLS verification disabled:
UreqHttpClient::new() (the default agent) reports a resource_report() estimate for its idle connection pool — up to 3 idle connections, each with a 16 KiB input and 16 KiB output buffer, so pool_connections: Some(3), pool_buffer_bytes: Some(96 * 1024), inflight_bytes: None. UreqHttpClient::with_agent(...) (a caller-supplied agent) reports None — its buffer and pool configuration is opaque, so the client doesn’t guess.
The execute method clones the agent and wraps the call in spawn_blocking:
The execute_streaming method is synchronous (no spawn_blocking) because it’s called from within a blocking context. It also uses the shared agent:
Implementing custom HTTP clients
You can implement custom HTTP clients for different runtimes or requirements.
Example: Reqwest client (async)
Example: mock client for testing
Usage with Bot builder
Best Practices
- Blocking operations - Always wrap blocking HTTP libraries in
tokio::task::spawn_blocking
- Streaming for large files - Use
execute_streaming for media downloads to avoid buffering
- Error handling - Return descriptive errors with context
- Timeouts - ureq 3.3 applies per-IP connection timeouts automatically; implement request-level timeouts for reliability
- Retries - Consider retry logic for transient failures
- Connection pooling - Use a shared
ureq::Agent (as UreqHttpClient does) for connection reuse
The HTTP client is primarily used for media operations in whatsapp-rust:
The client manages media connections internally. Use the high-level upload method instead of building requests manually:
Under the hood, the client uses the HTTP client to:
- Fetch media connection credentials from WhatsApp servers
- Encrypt the media with AES-256-CBC
- Upload to the CDN with proper auth headers
- Parse the response for
direct_path and file hashes
Testing
Unit test example
See Also