Zenwave
Zenwave is an ergonomic HTTP client framework for Rust with a unified API across native and WebAssembly targets.
Features
- Cross-platform - Same API on Linux, Windows, macOS, iOS, Android, and browsers/Workers
- Pluggable backends - Hyper (default), Apple URLSession, libcurl, or browser Fetch API
- Composable middleware - Timeout, retry, caching, cookies, redirects, OAuth2
- WebSocket support - Unified WebSocket client for native and browser
- Streaming - Upload/download large files without buffering (native only)
Quick Start
use ;
async
Installation
[]
= "0.2"
Backends
Zenwave provides multiple HTTP backends. The backend is selected at compile time.
| Backend | Platforms | TLS | Proxy | Notes |
|---|---|---|---|---|
| hyper (default) | All native | rustls or native-tls | Yes | Recommended for most use cases |
| curl | All native | System libcurl | Yes | Smaller binaries on systems with libcurl |
| apple | Apple platform(iOS, macOS, etc.) | Security.framework | No | Native Apple networking (experimental) |
| web | wasm32 | Browser | No | Automatic on wasm32, uses Fetch API, enforced CORS striction |
| web | wasm32 | Serverless | No | Automatic on wasm32, uses Fetch API, no CORS striction |
Backend Selection
# Default: Hyper with rustls
= "0.2"
# Hyper with platform-native TLS (OpenSSL/Security.framework/SChannel)
= { = "0.2", = false, = ["hyper-native-tls", "ws"] }
# libcurl backend
= { = "0.2", = false, = ["curl-backend"] }
# Apple URLSession (macOS/iOS only, experimental)
= { = "0.2", = false, = ["apple-backend"] }
On wasm32 targets, the web backend is always used automatically regardless of feature flags.
Platform Support
Native Platforms (Linux, Windows, macOS, Android, iOS)
Full feature support with the hyper backend:
- HTTP/HTTPS requests with configurable TLS
- Proxy support (HTTP CONNECT, SOCKS4/5)
- Persistent cookie storage
- File uploads/downloads with streaming
- Download resume via Range requests
- WebSocket with TLS
Android
Requires Android NDK for cross-compilation. See the Android build guide.
# Set environment and build
Browser (wasm32)
Uses the browser's native Fetch API:
| Feature | Available | Notes |
|---|---|---|
| HTTP/HTTPS | Yes | Browser handles TLS |
| Cookies | Browser-managed | Cannot access HttpOnly cookies from code |
| Proxy | No | Browser security restriction |
| File I/O | No | No filesystem access |
| WebSocket | Yes | Uses browser's WebSocket API |
Limitations: Cross-origin requests are subject to CORS. The server must send appropriate Access-Control-* headers or the browser will block the response. This cannot be bypassed from client code.
Cloudflare Workers (wasm32)
Uses the Workers Fetch API. Workers run server-side, so there are no CORS restrictions:
| Feature | Available | Notes |
|---|---|---|
| HTTP/HTTPS | Yes | Workers runtime handles TLS |
| Cookies | Yes | In-memory cookie jar (no persistent storage) |
| Proxy | No | Not supported by Workers runtime |
| File I/O | No | Use Workers KV or R2 instead |
| WebSocket | Yes | Via Workers WebSocket API |
Middleware
Compose middleware to add functionality:
use Duration;
use ;
let client = client
.timeout // Per-request timeout
.retry // Retry transport errors (not HTTP errors)
.follow_redirect // Follow up to 10 redirects
.enable_cache // RFC-compliant HTTP caching
.enable_cookie // In-memory cookie jar
.bearer_auth // Authorization header
.with;
Available Middleware
| Middleware | Method | Description |
|---|---|---|
| Timeout | .timeout(duration) |
Fails with 504 if exceeded |
| Retry | .retry(max) |
Retries on transport errors only |
| Redirect | .follow_redirect() |
Follows up to 10 redirects |
| Cache | .enable_cache() |
Honors Cache-Control, ETag, etc. |
| Cookies | .enable_cookie() |
In-memory cookie jar |
| Persistent Cookies | .enable_persistent_cookie() |
Saves to disk (native only) |
| Bearer Auth | .bearer_auth(token) |
Sets Authorization header |
| Basic Auth | .basic_auth(user, pass) |
Sets Authorization header |
| OAuth2 | .with(OAuth2ClientCredentials) |
Auto-refreshes tokens |
| Custom | .with(middleware) |
Your own middleware |
Request Building
use client;
let client = client;
// JSON request/response
let response: MyResponse = client
.post
.header
.bearer_auth
.json_body?
.json
.await?;
// Form data
let response = client
.post
.form_body?
.await?;
// Raw bytes
let response = client
.post
.bytes_body
.await?;
File Operations (Native Only)
// Stream file upload without buffering
client
.post
.file_body
.await?
.await?;
// Download with automatic resume
let report = client
.get
.download_to_path
.await?;
println!;
Proxy Support (Native Only)
use ;
// From environment (HTTP_PROXY, HTTPS_PROXY, NO_PROXY)
let client = client_with_proxy;
// Manual configuration
let proxy = builder
.http
.https
.no_proxy
.build;
let client = client_with_proxy;
Supports HTTP CONNECT and SOCKS4/4a/5/5h proxies. Only available with hyper and curl backends.
WebSocket
Cross-platform WebSocket client:
use ;
let socket = connect.await?;
socket.send_text.await?;
if let Some = socket.recv.await?
socket.close.await?;
Split for concurrent send/receive:
let = socket.split;
// Send from one task
sender.send_text.await?;
// Receive from another
while let Some = receiver.recv.await?
Feature Flags
| Feature | Description |
|---|---|
default |
hyper-backend + rustls + ws |
hyper-backend |
Hyper HTTP client |
rustls |
Pure Rust TLS (default, good for cross-compilation) |
native-tls |
Platform TLS (OpenSSL/Security.framework/SChannel) |
hyper-native-tls |
Shorthand for hyper-backend + native-tls |
hyper-rustls |
Shorthand for hyper-backend + rustls |
curl-backend |
libcurl-based backend |
apple-backend |
Apple URLSession (experimental) |
ws |
WebSocket support |
proxy |
Proxy support (auto-enabled with curl-backend) |
Examples
Run examples with cargo run --example <name>:
basic_get- Simple GET requestcustom_client- Middleware composition and JSONwebsocket_echo- WebSocket echo client
License
MIT License