product-os-request 0.0.52

Product OS : Request provides a fully featured HTTP request library combining elements of reqwest and ureq for both sync and async requests with a series of helper methods to allow for easier usage depending upon your needs for one-time or repeat usage.
Documentation
# 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

| Feature | reqwest_impl | hyper_impl | Status |
|---------|--------------|------------|--------|
| 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

| Feature | product-os-request | reqwest | hyper | ureq |
|---------|-------------------|---------|-------|------|
| 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