product-os-request 0.0.51

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)

[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)

[dependencies]
product-os-request = { version = "0.0.48", default-features = false, features = ["std_hyper"] }
tokio = { version = "1", features = ["full"] }

Backward Compatible (defaults to reqwest)

[dependencies]
product-os-request = "0.0.48"
tokio = { version = "1", features = ["full"] }

Quick Start

Simple GET Request (Reqwest)

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)

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

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:

[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:

[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

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

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

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.

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

Changelog

See CHANGELOG.md for version history and changes.

Testing

Run the test suite:

# 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