Crate http_cache_tower

Crate http_cache_tower 

Source
Expand description

HTTP caching middleware for Tower services and Axum applications.

This crate provides Tower layers that implement HTTP caching according to RFC 7234. It supports both traditional buffered caching and streaming responses for large payloads.

§Basic Usage

§With Tower Services

use http_cache_tower::{HttpCacheLayer, CACacheManager};
use http_cache::{CacheMode, HttpCache, HttpCacheOptions};
use tower::ServiceBuilder;
use tower::service_fn;
use tower::ServiceExt;
use http::{Request, Response};
use http_body_util::Full;
use bytes::Bytes;
use std::convert::Infallible;

async fn handler(_req: Request<Full<Bytes>>) -> Result<Response<Full<Bytes>>, Infallible> {
    Ok(Response::new(Full::new(Bytes::from("Hello, World!"))))
}

#[tokio::main]
async fn main() {
    // Create cache manager with disk storage
    let cache_manager = CACacheManager::new("./cache".into(), true);
     
    // Create cache layer
    let cache_layer = HttpCacheLayer::new(cache_manager);
     
    // Build service with caching
    let service = ServiceBuilder::new()
        .layer(cache_layer)
        .service_fn(handler);
     
    // Use the service
    let request = Request::builder()
        .uri("http://example.com")
        .body(Full::new(Bytes::new()))
        .unwrap();
    let response = service.oneshot(request).await.unwrap();
}

§With Custom Cache Configuration

use http_cache_tower::{HttpCacheLayer, CACacheManager};
use http_cache::{CacheMode, HttpCache, HttpCacheOptions};

// Create cache manager
let cache_manager = CACacheManager::new("./cache".into(), true);

// Configure cache behavior
let cache = HttpCache {
    mode: CacheMode::Default,
    manager: cache_manager,
    options: HttpCacheOptions::default(),
};

// Create layer with custom cache
let cache_layer = HttpCacheLayer::with_cache(cache);

§Streaming Support

For handling large responses without buffering, use StreamingManager:

use http_cache_tower::HttpCacheStreamingLayer;
use http_cache::StreamingManager;
use std::path::PathBuf;

// Create streaming cache setup
let streaming_manager = StreamingManager::new("./streaming-cache".into());
let streaming_layer = HttpCacheStreamingLayer::new(streaming_manager);

// Use with your service
// let service = streaming_layer.layer(your_service);

§Cache Modes

Different cache modes provide different behaviors:

  • CacheMode::Default: Follow HTTP caching rules strictly
  • CacheMode::NoStore: Never cache responses
  • CacheMode::NoCache: Always revalidate with the origin server
  • CacheMode::ForceCache: Cache responses even if headers suggest otherwise
  • CacheMode::OnlyIfCached: Only serve from cache, never hit origin server
  • CacheMode::IgnoreRules: Cache everything regardless of headers

§Cache Invalidation

The middleware automatically handles cache invalidation for unsafe HTTP methods:

These methods will invalidate any cached GET response for the same URI:
- PUT /api/users/123    -> invalidates GET /api/users/123
- POST /api/users/123   -> invalidates GET /api/users/123  
- DELETE /api/users/123 -> invalidates GET /api/users/123
- PATCH /api/users/123  -> invalidates GET /api/users/123

§Integration with Other Tower Layers

The cache layer works with other Tower middleware:

use tower::ServiceBuilder;
use http_cache_tower::{HttpCacheLayer, CACacheManager};
use tower::service_fn;
use tower::ServiceExt;
use http::{Request, Response};
use http_body_util::Full;
use bytes::Bytes;
use std::convert::Infallible;

async fn handler(_req: Request<Full<Bytes>>) -> Result<Response<Full<Bytes>>, Infallible> {
    Ok(Response::new(Full::new(Bytes::from("Hello, World!"))))
}

#[tokio::main]
async fn main() {
    let cache_manager = CACacheManager::new("./cache".into(), true);
    let cache_layer = HttpCacheLayer::new(cache_manager);

    let service = ServiceBuilder::new()
        // .layer(TraceLayer::new_for_http())  // Logging (requires tower-http)
        // .layer(CompressionLayer::new())     // Compression (requires tower-http)
        .layer(cache_layer)                    // Caching
        .service_fn(handler);
     
    // Use the service
    let request = Request::builder()
        .uri("http://example.com")
        .body(Full::new(Bytes::new()))
        .unwrap();
    let response = service.oneshot(request).await.unwrap();
}

Structs§

CACacheManager
Implements CacheManager with cacache as the backend.
HttpCacheLayer
HTTP cache layer for Tower services.
HttpCacheService
HTTP cache service for Tower/Hyper

Enums§

HttpCacheBody
Body type that wraps cached responses
HttpCacheError
Unified error type for HTTP cache operations that works across all client libraries.