web-server-abstraction 1.0.0

An ergonomic abstraction layer over popular Rust web frameworks
Documentation

Web Server Abstraction

An ergonomic abstraction layer over popular Rust web frameworks, allowing you to write web applications once and run them on any supported framework.

Features

  • Framework Agnostic: Write once, run on any supported framework
  • Type Safe: Leverages Rust's type system for compile-time guarantees
  • Async First: Built for modern async Rust with native async/await support
  • Middleware Support: Composable middleware system for cross-cutting concerns
  • Tower Integration: Built on the Tower ecosystem for compatibility
  • Ergonomic API: Clean, intuitive API that's easy to learn and use
  • Advanced Routing: Path parameters (:id) and wildcards (*file) support
  • WebSocket Ready: Built-in WebSocket upgrade handling and message types
  • HTTP Method Shortcuts: Convenient .get(), .post(), .put(), etc. methods
  • Rich Middleware: 9+ built-in middleware types for common web patterns
  • Performance Optimized: Comprehensive benchmarking and profiling infrastructure

Supported Frameworks

Framework Feature Flag Status
Mock (Testing) Default ✅ Complete
Axum axum ✅ Complete
Actix-Web actix-web ✅ Complete
Warp warp ✅ Complete
Rocket rocket ✅ Complete
Salvo salvo ✅ Complete
Poem poem ✅ Complete

Quick Start

Add this to your Cargo.toml:

[dependencies]
web-server-abstraction = "1.0.0"

# Enable specific framework support
web-server-abstraction = { version = "1.0.0", features = ["axum"] }

Basic Example

use web_server_abstraction::{
    WebServer, HttpMethod, Response, StatusCode,
    middleware::{LoggingMiddleware, CorsMiddleware},
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let server = WebServer::new()
        // Add middleware
        .middleware(LoggingMiddleware::new())
        .middleware(CorsMiddleware::new().allow_origin("*"))

        // Add routes
        .route("/", HttpMethod::GET, |_req| async {
            Ok(Response::ok().body("Hello, World!"))
        })
        .route("/health", HttpMethod::GET, |_req| async {
            Ok(Response::ok().body("OK"))
        })
        .route("/users", HttpMethod::POST, |req| async {
            // Parse JSON body
            let user: serde_json::Value = req.json().await?;
            Ok(Response::new(StatusCode::CREATED)
                .header("content-type", "application/json")
                .body(serde_json::to_string(&user)?))
        });

    // Bind and run the server
    let bound_server = server.bind("127.0.0.1:3000").await?;
    println!("Server running on http://127.0.0.1:3000");
    bound_server.run().await?;

    Ok(())
}

Framework-Specific Adapters

use web_server_abstraction::WebServer;

// Use specific framework adapters
#[cfg(feature = "axum")]
let server = WebServer::with_axum_adapter();

#[cfg(feature = "actix-web")]
let server = WebServer::with_actix_adapter();

#[cfg(feature = "warp")]
let server = WebServer::with_warp_adapter();

// Or use the mock adapter for testing
let server = WebServer::with_mock_adapter();

Architecture

Core Abstractions

The crate is built around several key abstractions:

  1. WebServer: The main entry point for building web applications
  2. Handler: Trait for request handlers that convert requests to responses
  3. Middleware: Composable middleware for cross-cutting concerns
  4. Adapter: Framework-specific implementations that bridge to actual web frameworks

Type System

// Core types are standardized across frameworks
pub struct Request { /* ... */ }
pub struct Response { /* ... */ }
pub enum HttpMethod { GET, POST, PUT, DELETE, /* ... */ }
pub struct StatusCode(pub u16);

Middleware System

Built-in middleware includes:

  • LoggingMiddleware: Request/response logging with configurable detail levels
  • CorsMiddleware: Cross-Origin Resource Sharing with full configuration support
  • AuthMiddleware: Authentication checks with bearer token validation
  • TimeoutMiddleware: Request timeouts with configurable durations
  • RateLimitMiddleware: Rate limiting with sliding window algorithm
  • CompressionMiddleware: Response compression (gzip, deflate)
  • SecurityHeadersMiddleware: Security headers (HSTS, CSP, X-Frame-Options, etc.)
  • MetricsMiddleware: Request metrics collection and monitoring
  • CacheMiddleware: Response caching with TTL and invalidation strategies
use web_server_abstraction::middleware::*;

let server = WebServer::new()
    .middleware(LoggingMiddleware::new().log_bodies(true))
    .middleware(CorsMiddleware::new()
        .allow_origin("https://example.com")
        .allow_methods(vec!["GET".to_string(), "POST".to_string()])
        .allow_credentials(true))
    .middleware(AuthMiddleware::new()
        .with_bearer_tokens(vec!["secret-token".to_string()]))
    .middleware(RateLimitMiddleware::new(100, Duration::from_secs(60)))
    .middleware(CompressionMiddleware::new().min_size(1024))
    .middleware(SecurityHeadersMiddleware::new())
    .middleware(MetricsMiddleware::new())
    .middleware(CacheMiddleware::new(Duration::from_secs(300)));

Framework Integration Plan

Current Design Principles

  1. Common HTTP Abstractions: Use standardized types from the http crate
  2. Tower Compatibility: Leverage the Tower ecosystem where possible
  3. Zero-Cost Abstractions: Minimal runtime overhead
  4. Ergonomic APIs: Focus on developer experience

Adapter Implementation Strategy

Each framework adapter follows this pattern:

// 1. Convert our types to framework types
fn convert_request(req: Request) -> FrameworkRequest;
fn convert_response(resp: FrameworkResponse) -> Response;

// 2. Implement the adapter interface
impl FrameworkAdapter {
    pub async fn bind(&mut self, addr: &str) -> Result<()>;
    pub async fn run(self) -> Result<()>;
    pub fn route(&mut self, path: &str, method: HttpMethod, handler: HandlerFn);
    pub fn middleware(&mut self, middleware: Box<dyn Middleware>);
}

Integration Status

Axum ✅ COMPLETE

  • ✅ Basic route registration
  • ✅ Request/response type conversion
  • ✅ Middleware integration with Tower ServiceBuilder
  • ✅ Full HTTP method support
  • ✅ Async handler support

Actix-Web ✅ COMPLETE

  • ✅ Route registration and handlers
  • ✅ Request/response conversion
  • ✅ HTTP server binding and running
  • ✅ Built-in logging middleware
  • ✅ Full HTTP method support

Warp ✅ COMPLETE

  • ✅ Filter-based routing system
  • ✅ Request/response handling
  • ✅ Middleware composition
  • ✅ Async handler support
  • ✅ Server binding and execution

Rocket ✅ COMPLETE

  • ✅ Production-ready adapter implementation
  • ✅ Route registration with Rocket's Handler trait
  • ✅ Request/response type conversion
  • ✅ Middleware integration via Fairings
  • ✅ Full HTTP method support
  • ✅ Server configuration and binding
  • ✅ Comprehensive error handling

Salvo ✅ COMPLETE

  • ✅ Production-ready adapter implementation
  • ✅ High-performance web framework integration
  • ✅ Modular design with extractors
  • ✅ Router and Service integration
  • ✅ Middleware fairing system
  • ✅ Full HTTP method support
  • ✅ TcpListener binding and server execution

Poem ✅ COMPLETE

  • ✅ Production-ready adapter implementation
  • ✅ Fast and lightweight framework integration
  • ✅ Type-safe Endpoint trait implementation
  • ✅ Built-in middleware (Tracing, NormalizePath)
  • ✅ Comprehensive request/response conversion
  • ✅ Full HTTP method support
  • ✅ TcpListener and Server integration

Testing

The crate includes a mock adapter for easy testing:

#[tokio::test]
async fn test_my_routes() {
    use web_server_abstraction::MockAdapter;

    let server = WebServer::with_mock_adapter()
        .route("/test", HttpMethod::GET, |_| async {
            Ok(Response::ok().body("test"))
        });

    let bound_server = server.bind("127.0.0.1:0").await.unwrap();

    // Mock adapter provides testing utilities
    // (In practice, you'd make actual HTTP requests)
}

Run tests with:

cargo test

Run examples with:

cargo run --example basic_server

Contributing

We welcome contributions! Areas where help is needed:

  1. Framework Adapters: Implementing adapters for different frameworks
  2. Middleware: Adding common middleware implementations
  3. Documentation: Improving docs and examples
  4. Testing: Adding comprehensive test coverage
  5. Performance: Benchmarking and optimization

Adding a New Framework Adapter

  1. Create a new module in src/adapters/
  2. Implement the required methods: bind, run, route, middleware
  3. Add conversion functions between framework types and our types
  4. Add a feature flag in Cargo.toml
  5. Update the AdapterType enum in core.rs
  6. Add tests and documentation

Performance Considerations

  • Zero-cost abstractions: The abstraction layer adds minimal overhead
  • Compile-time dispatch: Framework adapters use static dispatch where possible
  • Memory efficiency: Minimal allocations in hot paths
  • Async-first: Built for modern async Rust performance characteristics

Benchmarking and Profiling

The crate includes comprehensive benchmarking infrastructure:

use web_server_abstraction::benchmarks::{
    PerformanceProfiler, BenchmarkConfig, BenchmarkSuite
};

// Configure and run performance benchmarks
let config = BenchmarkConfig {
    duration: Duration::from_secs(30),
    concurrent_requests: 100,
    warmup_duration: Duration::from_secs(5),
};

let profiler = PerformanceProfiler::new(config);
let results = profiler.benchmark_scenario("load_test").await?;

// Analyze results with statistical metrics
println!("Average response time: {:?}", results.mean());
println!("95th percentile: {:?}", results.percentile(95.0));
println!("Requests per second: {}", results.requests_per_second());

Features include:

  • Statistical Analysis: Mean, median, percentiles, standard deviation
  • Memory Profiling: Memory usage tracking and leak detection
  • Scenario Comparison: Compare performance across different configurations
  • Optimization Recommendations: Automated performance suggestions
  • Async-first: Built for modern async Rust performance characteristics

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.

Roadmap

Version 0.1.0 ✅ COMPLETED

  • Core abstractions and API design
  • Mock adapter for testing
  • Basic middleware system
  • Documentation and examples

Version 0.2.0 ✅ COMPLETED

  • Complete Axum adapter
  • Actix-Web adapter
  • Enhanced middleware ecosystem (9 middleware types implemented)
  • Performance benchmarks and profiling infrastructure

Version 0.3.0 ✅ COMPLETED

  • Warp adapter
  • Advanced routing features (path parameters, wildcards)
  • WebSocket support (basic implementation)
  • HTTP method convenience functions (get, post, put, delete, patch)
  • Framework adapter scaffolding (Rocket, Salvo, Poem - basic structure in place)

Version 1.0.0 ✅ COMPLETED

  • Complete Rocket adapter
  • Complete Salvo adapter
  • Complete Poem adapter
  • Comprehensive middleware library
  • Production-ready performance
  • Stable API
  • WebSocket support
  • Advanced routing features (wildcards, parameters)
  • Mountable interface support
  • Authentication integration## Why This Approach?

Problem Statement

Many Rust crates need to support multiple web frameworks, leading to:

  • Duplicate implementation effort
  • Maintenance burden across multiple framework versions
  • User lock-in to specific frameworks
  • Inconsistent APIs across different framework integrations

Solution Benefits

  1. Write Once, Run Anywhere: Implement your web logic once
  2. Framework Flexibility: Users can choose their preferred framework
  3. Easier Testing: Mock adapter makes testing straightforward
  4. Future-Proof: Easy to add support for new frameworks
  5. Consistent API: Same interface regardless of underlying framework

Trade-offs

  • Additional Abstraction: One more layer between your code and the framework
  • Learning Curve: New API to learn (though designed to be intuitive)
  • Feature Lag: Advanced framework-specific features may not be immediately available

We believe the benefits outweigh these trade-offs for most use cases, especially for libraries and applications that need broad framework compatibility.