1 stable release
| 1.0.0 | Jun 5, 2025 |
|---|---|
| 0.1.0 |
|
#363 in HTTP client
140KB
2K
SLoC
fetchttp
A WHATWG Fetch API compliant HTTP client library for Rust that provides the familiar fetch() interface you know and love from web development.
✨ Features
- 🌐 WHATWG Fetch API Compliant - Follows the official specification
- 🚀 Async/Await Support - Built on Tokio for modern async Rust
- 🔒 Type Safety - Leverages Rust's type system for safe HTTP operations
- 📦 JSON Support - Built-in JSON serialization/deserialization with serde
- 🔧 Flexible Bodies - Support for text, bytes, and JSON request/response bodies
- 📋 Header Management - Complete header manipulation API
- 🔄 Request/Response Cloning - Efficient cloning following the specification
- ⏹️ Abort Signals - Request cancellation support
- 🔗 Connection Pooling - Automatic connection reuse for better performance
🚀 Quick Start
Add fetchttp to your Cargo.toml:
[dependencies]
fetchttp = "0.1.0"
tokio = { version = "1.0", features = ["full"] }
serde_json = "1.0" # For JSON support
Simple GET Request
use fetchttp::*;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let response = fetch("https://api.github.com/users/octocat", None).await?;
if response.ok() {
let user: serde_json::Value = response.json().await?;
println!("User: {}", user["name"]);
}
Ok(())
}
POST Request with JSON
use fetchttp::*;
use serde_json::json;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let data = json!({
"name": "John Doe",
"email": "john@example.com"
});
let mut init = RequestInit::new();
init.method = Some("POST".to_string());
init.body = Some(ReadableStream::from_json(&data));
let response = fetch("https://api.example.com/users", Some(init)).await?;
if response.ok() {
println!("User created successfully!");
}
Ok(())
}
Custom Headers
use fetchttp::*;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut headers = Headers::new();
headers.set("Authorization", "Bearer your-token")?;
headers.set("User-Agent", "MyApp/1.0")?;
let mut init = RequestInit::new();
init.headers = Some(headers);
let response = fetch("https://api.example.com/protected", Some(init)).await?;
let text = response.text().await?;
println!("Response: {}", text);
Ok(())
}
Request Cancellation
use fetchttp::*;
use std::time::Duration;
use tokio::time::sleep;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let controller = AbortController::new();
let signal = controller.signal().clone();
let mut init = RequestInit::new();
init.signal = Some(signal);
// Cancel the request after 1 second
tokio::spawn(async move {
sleep(Duration::from_secs(1)).await;
controller.abort();
});
match fetch("https://httpbin.org/delay/5", Some(init)).await {
Ok(response) => println!("Request completed: {}", response.status()),
Err(FetchError::Abort(_)) => println!("Request was cancelled"),
Err(e) => println!("Request failed: {}", e),
}
Ok(())
}
📚 API Reference
Core Functions
fetch(url, init)- Perform an HTTP request
Request Types
Request- Represents an HTTP requestRequestInit- Configuration for requestsRequestMode- CORS mode settingsRequestCredentials- Credential handlingRequestCache- Cache controlRequestRedirect- Redirect handling
Response Types
Response- Represents an HTTP responseResponseInit- Configuration for responsesResponseType- Response type information
Body and Streams
ReadableStream- Request/response body handlingHeaders- HTTP header management
Error Handling
FetchError- Main error typeTypeError- Type validation errorsNetworkError- Network-related errorsAbortError- Request cancellation errors
Abort Support
AbortController- Controls request cancellationAbortSignal- Signals request cancellation
🔄 Body Consumption
Response and request bodies can be consumed in multiple ways:
// Text
let text = response.text().await?;
// JSON
let data: MyStruct = response.json().await?;
// Bytes
let bytes = response.array_buffer().await?;
// Blob (alias for array_buffer)
let blob = response.blob().await?;
🛡️ Error Handling
The library provides comprehensive error handling:
match fetch("https://example.com", None).await {
Ok(response) => {
if response.ok() {
println!("Success: {}", response.status());
} else {
println!("HTTP Error: {}", response.status());
}
}
Err(FetchError::Type(e)) => {
eprintln!("Type error: {}", e);
}
Err(FetchError::Network(e)) => {
eprintln!("Network error: {}", e);
}
Err(FetchError::Abort(e)) => {
eprintln!("Request aborted: {}", e);
}
}
🔧 Advanced Usage
Custom HTTP Methods
let mut init = RequestInit::new();
init.method = Some("PATCH".to_string());
init.body = Some(ReadableStream::from_json(&data));
let response = fetch("https://api.example.com/resource/1", Some(init)).await?;
File Upload
use std::fs;
let file_content = fs::read("document.pdf")?;
let mut init = RequestInit::new();
init.method = Some("POST".to_string());
init.body = Some(ReadableStream::from_bytes(file_content.into()));
let response = fetch("https://api.example.com/upload", Some(init)).await?;
Response Headers
let response = fetch("https://httpbin.org/response-headers", None).await?;
for (name, value) in response.headers().entries() {
println!("{}: {}", name, value);
}
// Check specific header
if let Some(content_type) = response.headers().get("content-type")? {
println!("Content-Type: {}", content_type);
}
🏗️ Building and Testing
# Build the library
cargo build
# Run tests
cargo test
# Run benchmarks
cargo bench
# Generate documentation
cargo doc --open
📊 Performance
The library is designed for performance with:
- Connection pooling via hyper
- Efficient body streaming
- Zero-copy operations where possible
- Minimal allocations
See benches/ for detailed performance benchmarks.
🤝 Contributing
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🌟 Comparison with Other Libraries
| Feature | fetchttp | reqwest | hyper | ureq |
|---|---|---|---|---|
| WHATWG Fetch API | ✅ | ❌ | ❌ | ❌ |
| Async/Await | ✅ | ✅ | ✅ | ❌ |
| JSON Support | ✅ | ✅ | ❌ | ✅ |
| Connection Pooling | ✅ | ✅ | ✅ | ❌ |
| Abort Signals | ✅ | ✅ | ❌ | ❌ |
| Web API Compatibility | ✅ | ❌ | ❌ | ❌ |
🔗 Links
Made with ❤️ by MuntasirSZN
Dependencies
~9–25MB
~331K SLoC