# Product OS : Request
Product OS : Request provides a fully featured HTTP request library with multiple implementation choices, allowing you to select between reqwest (high-level) or hyper (low-level) backends while maintaining a consistent API.
## Features
- **Multiple Implementations** - Choose between reqwest or hyper backends
- **Async HTTP Requests** - Built on tokio for high-performance async I/O
- **Default HTTPS/TLS** - Secure by default using Rustls
- **Requester Pattern** - Reusable configuration for multiple requests
- **Custom Request/Response Types** - Type-safe request building and response handling
- **Proxy Support** - HTTP, HTTPS, and SOCKS5 proxy configuration
- **Redirect Policies** - Configurable redirect handling
- **Certificate Management** - Custom trusted certificates support
- **Streaming Responses** - Optional streaming support for large responses
- **no_std Support** - Works in no_std environments with alloc
- **Comprehensive Documentation** - Well-documented with examples
## Installation
### Using Reqwest (High-Level, More Features)
```toml
[dependencies]
product-os-request = { version = "0.0.48", default-features = false, features = ["std_reqwest"] }
tokio = { version = "1", features = ["full"] }
```
### Using Hyper (Low-Level, More Control)
```toml
[dependencies]
product-os-request = { version = "0.0.48", default-features = false, features = ["std_hyper"] }
tokio = { version = "1", features = ["full"] }
```
### Backward Compatible (defaults to reqwest)
```toml
[dependencies]
product-os-request = "0.0.48"
tokio = { version = "1", features = ["full"] }
```
## Quick Start
### Simple GET Request (Reqwest)
```rust
use product_os_request::{Method, ProductOSRequestClient, ProductOSRequester, ProductOSClient};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create and configure requester
let mut requester = ProductOSRequester::new();
requester.set_timeout(5000);
// Create client
let mut client = ProductOSRequestClient::new();
requester.build(&mut client);
// Make request
let request = client.new_request(Method::GET, "https://api.example.com/data");
let response = client.request(request).await?;
println!("Status: {}", response.status_code());
let text = client.text(response).await?;
println!("Response: {}", text);
Ok(())
}
```
### Simple GET Request (Hyper)
```rust
use product_os_request::{Method, ProductOSHyperClient, ProductOSRequester, ProductOSClient};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create and configure requester
let mut requester = ProductOSRequester::new();
requester.set_timeout(5000);
// Create hyper-based client
let mut client = ProductOSHyperClient::new();
requester.build(&mut client);
// Make request
let request = client.new_request(Method::GET, "https://api.example.com/data");
let response = client.request(request).await?;
println!("Status: {}", response.status_code());
let text = client.text(response).await?;
println!("Response: {}", text);
Ok(())
}
```
### POST with JSON
```rust
use product_os_request::{Method, ProductOSRequestClient, ProductOSRequester, ProductOSClient};
use serde_json::json;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut requester = ProductOSRequester::new();
let mut client = ProductOSRequestClient::new();
requester.build(&mut client);
let mut request = client.new_request(Method::POST, "https://api.example.com/users");
request.add_header("Content-Type", "application/json", false);
let json_data = json!({
"name": "John Doe",
"email": "john@example.com"
});
client.set_body_json(&mut request, json_data).await;
let response = client.request(request).await?;
let json_response = client.json(response).await?;
println!("Response: {:#}", json_response);
Ok(())
}
```
## Features
Product OS Request supports optional features that can be enabled as needed:
```toml
[dependencies]
product-os-request = { version = "0.0.48", features = ["json", "form", "stream"] }
```
Available features:
- **`std`** (default) - Full standard library support with reqwest integration
- **`json`** - JSON serialization/deserialization support
- **`form`** - Form-encoded body support
- **`stream`** - Streaming response support
- **`method`** - Method enum only (no_std compatible)
- **`request`** - Request building (no_std compatible)
- **`response`** - Response handling (no_std compatible)
### no_std Support
To use in a no_std environment:
```toml
[dependencies]
product-os-request = { version = "0.0.48", default-features = false, features = ["method", "request"] }
```
## Examples
The library includes comprehensive examples in this README demonstrating common use cases.
### Simple GET Request Example
## Configuration Options
### Requester Configuration
```rust
let mut requester = ProductOSRequester::new();
// Timeouts
requester.set_timeout(5000); // Request timeout in ms
requester.set_connect_timeout(2000); // Connection timeout in ms
// Security
requester.force_secure(true); // HTTPS only
requester.trust_all_certificates(false); // Certificate validation
// Redirects
use product_os_request::RedirectPolicy;
requester.set_redirect_policy(RedirectPolicy::Limit(5));
// Proxy
use product_os_request::Protocol;
requester.set_proxy(Some((Protocol::HTTP, String::from("proxy.example.com:8080"))));
// Custom certificates
let cert_der = include_bytes!("cert.der");
requester.add_trusted_certificate_pem(cert_der.to_vec());
// Default headers
requester.add_header("User-Agent", "MyApp/1.0", false);
```
### Request Building
```rust
let mut request = client.new_request(Method::POST, "https://api.example.com/data");
// Headers
request.add_header("Content-Type", "application/json", false);
request.add_header("X-API-Key", "secret", true); // marked as sensitive
// Authentication
request.bearer_auth(String::from("your-token"));
// Query parameters
request.add_param(String::from("page"), String::from("1"));
request.add_param(String::from("limit"), String::from("10"));
// Body
use bytes::Bytes;
use product_os_http_body::BodyBytes;
let body = BodyBytes::new(Bytes::from("request body"));
request.set_body(body);
```
### Response Handling
```rust
let response = client.request(request).await?;
// Status
let status = response.status_code();
println!("Status: {}", status);
// Headers
let headers = response.get_headers();
for (name, value) in headers {
println!("{}: {}", name, value);
}
// URL (after redirects)
let url = response.response_url();
// Body as text
let text = client.text(response).await?;
// Body as JSON
let json = client.json(response).await?;
// Body as bytes
let bytes = client.bytes(response).await?;
```
## API Documentation
For detailed API documentation, visit [docs.rs/product-os-request](https://docs.rs/product-os-request).
## What is Product OS?
Product OS is a collection of packages that provide different tools and features that can work together to build products more easily for the Rust ecosystem.
## Contributing
Contributions are not currently available but will be available on a public repository soon.
## License
[GNU GPLv3](https://choosealicense.com/licenses/gpl-3.0/)
## Changelog
See [CHANGELOG.md](CHANGELOG.md) for version history and changes.
## Testing
Run the test suite:
```bash
# Test reqwest implementation
cargo test --no-default-features --features "std_reqwest,json"
# Test hyper implementation
cargo test --no-default-features --features "std_hyper,json"
# Test both implementations
cargo test --no-default-features --features "std_reqwest,json" && \
cargo test --no-default-features --features "std_hyper,json"
# Specific feature combination
cargo test --no-default-features --features method,request
# With output
cargo test --no-default-features --features "std_hyper,json" -- --nocapture
```
## Implementation Comparison
Product OS Request offers two HTTP client implementations:
### Reqwest Implementation (`std_reqwest`)
**Pros:**
- Battle-tested, mature library
- More convenience features out of the box
- Simpler internal architecture
- Well-documented ecosystem
**Cons:**
- Larger dependency tree
- Less control over low-level details
- Updates depend on upstream reqwest releases
### Hyper Implementation (`std_hyper`)
**Pros:**
- Lower-level control over HTTP behavior
- Smaller dependency tree
- Direct access to hyper's connection management
- More customization options
- Potentially better performance
**Cons:**
- More complex internal implementation
- Some features require manual implementation
- Less mature than reqwest integration
### Feature Parity Matrix
| GET/POST/etc | ✅ | ✅ | Full parity |
| Headers | ✅ | ✅ | Full parity |
| Query params | ✅ | ✅ | Full parity |
| Request body | ✅ | ✅ | Full parity |
| JSON body | ✅ | ✅ | Full parity |
| Form body | ✅ | ✅ | Full parity |
| Timeouts | ✅ | ⚠️ | Partial (configured, not enforced yet) |
| Redirects | ✅ | ✅ | Full parity |
| Proxies (HTTP/HTTPS) | ✅ | ⚠️ | Planned |
| Proxies (SOCKS5) | ✅ | ⚠️ | Planned |
| TLS/HTTPS | ✅ | ✅ | Full parity |
| Custom certs | ✅ | ✅ | Full parity |
| Trust all certs | ✅ | ✅ | Full parity |
| Compression | ✅ | ⚠️ | Dependencies added, not integrated |
| Cookies | ✅ | ⚠️ | Dependencies added, not integrated |
| Streaming | ✅ | ✅ | Full parity |
| Connection pooling | ✅ | ✅ | Full parity |
**Status Legend:**
- ✅ Fully implemented and tested
- ⚠️ Partial implementation or dependencies added
- ❌ Not implemented
## Performance
Product OS Request supports multiple backends:
**Reqwest-based:**
- Async/await support for efficient concurrency
- Connection pooling and reuse
- HTTP/2 support
- Compression support (gzip, brotli)
- Streaming for large responses
**Hyper-based:**
- Direct hyper integration for lower overhead
- Fine-tuned connection pool settings
- HTTP/1 and HTTP/2 support
- Streaming with native hyper Body traits
- Reduced abstraction layers
## Safety
This library:
- Uses `#![warn(clippy::unwrap_used)]` to avoid panics
- Provides proper error handling throughout
- Supports no_std for embedded environments
- Has comprehensive test coverage (112+ tests)
## Comparison with Other Libraries
| Async | ✅ | ✅ | ✅ | ❌ |
| Sync | ❌ | ✅ (blocking) | ❌ | ✅ |
| no_std | ✅ | ❌ | ❌ | ❌ |
| Builder Pattern | ✅ | ✅ | ⚠️ | ✅ |
| Streaming | ✅ | ✅ | ✅ | ❌ |
| Type-safe | ✅ | ✅ | ✅ | ✅ |
| Multiple Backends | ✅ | ❌ | N/A | ❌ |
| Requester Pattern | ✅ | ❌ | ❌ | ❌ |
Product OS Request provides a unique combination of features:
- **Abstraction Layer**: Unified API across multiple HTTP client implementations
- **Requester Pattern**: Reusable configuration for managing multiple requests
- **Implementation Choice**: Select between high-level (reqwest) or low-level (hyper) backends
- **no_std Support**: Core types work in constrained environments
- **Consistent API**: Same code works with different backends