Crate http_cache_reqwest

Crate http_cache_reqwest 

Source
Expand description

§http-cache-reqwest

HTTP caching middleware for the reqwest HTTP client.

This middleware implements HTTP caching according to RFC 7234 for the reqwest HTTP client library. It works as part of the [reqwest-middleware] ecosystem to provide caching capabilities.

use reqwest::Client;
use reqwest_middleware::{ClientBuilder, Result};
use http_cache_reqwest::{Cache, CacheMode, CACacheManager, HttpCache, HttpCacheOptions};

#[tokio::main]
async fn main() -> Result<()> {
    let client = ClientBuilder::new(Client::new())
        .with(Cache(HttpCache {
            mode: CacheMode::Default,
            manager: CACacheManager::new("./cache".into(), true),
            options: HttpCacheOptions::default(),
        }))
        .build();
     
    // This request will be cached according to response headers
    let response = client
        .get("https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching")
        .send()
        .await?;
    println!("Status: {}", response.status());
     
    // Subsequent identical requests may be served from cache
    let cached_response = client
        .get("https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching")
        .send()
        .await?;
    println!("Cached status: {}", cached_response.status());
     
    Ok(())
}

§Streaming Support

The StreamingCache provides streaming support for large responses without buffering them entirely in memory. This is particularly useful for downloading large files or processing streaming APIs while still benefiting from HTTP caching.

Note: Requires the streaming feature and a compatible cache manager that implements StreamingCacheManager. Currently only the StreamingCacheManager supports streaming - CACacheManager and MokaManager do not support streaming and will buffer responses in memory. The streaming implementation achieves significant memory savings (typically 35-40% reduction) compared to traditional buffered approaches.

use reqwest::Client;
use reqwest_middleware::ClientBuilder;
use http_cache_reqwest::{StreamingCache, CacheMode};
use http_cache::StreamingManager;

#[tokio::main]
async fn main() -> reqwest_middleware::Result<()> {
    let client = ClientBuilder::new(Client::new())
        .with(StreamingCache::new(
            StreamingManager::new("./cache".into()),
            CacheMode::Default,
        ))
        .build();
         
    // Stream large responses efficiently - cached responses are also streamed
    let response = client
        .get("https://httpbin.org/stream/1000")
        .send()
        .await?;
    println!("Status: {}", response.status());
     
    // Process the streaming body chunk by chunk
    use futures_util::StreamExt;
    let mut stream = response.bytes_stream();
    while let Some(chunk) = stream.next().await {
        let chunk = chunk?;
        println!("Received chunk of {} bytes", chunk.len());
        // Process chunk without loading entire response into memory
    }
     
    Ok(())
}

§Streaming Cache with Custom Options

use reqwest::Client;
use reqwest_middleware::ClientBuilder;
use http_cache_reqwest::{StreamingCache, CacheMode, HttpCacheOptions};
use http_cache::StreamingManager;

#[tokio::main]
async fn main() -> reqwest_middleware::Result<()> {
    let options = HttpCacheOptions {
        cache_bust: Some(std::sync::Arc::new(|req: &http::request::Parts, _cache_key: &Option<std::sync::Arc<dyn Fn(&http::request::Parts) -> String + Send + Sync>>, _uri: &str| {
            // Custom cache busting logic for streaming requests
            if req.uri.path().contains("/stream/") {
                vec![format!("stream:{}", req.uri)]
            } else {
                vec![]
            }
        })),
        ..Default::default()
    };

    let client = ClientBuilder::new(Client::new())
        .with(StreamingCache::with_options(
            StreamingManager::new("./cache".into()),
            CacheMode::Default,
            options,
        ))
        .build();
         
    Ok(())
}

§Cache Modes

Control caching behavior with different modes:

use reqwest::Client;
use reqwest_middleware::ClientBuilder;
use http_cache_reqwest::{Cache, CacheMode, CACacheManager, HttpCache, HttpCacheOptions};

#[tokio::main]
async fn main() -> reqwest_middleware::Result<()> {
    let client = ClientBuilder::new(Client::new())
        .with(Cache(HttpCache {
            mode: CacheMode::ForceCache, // Cache everything, ignore headers
            manager: CACacheManager::new("./cache".into(), true),
            options: HttpCacheOptions::default(),
        }))
        .build();
     
    // This will be cached even if headers say not to cache
    client.get("https://httpbin.org/uuid").send().await?;
    Ok(())
}

§Per-Request Cache Control

Override the cache mode on individual requests:

use reqwest::Client;
use reqwest_middleware::ClientBuilder;
use http_cache_reqwest::{Cache, CacheMode, CACacheManager, HttpCache, HttpCacheOptions};

#[tokio::main]
async fn main() -> reqwest_middleware::Result<()> {
    let client = ClientBuilder::new(Client::new())
        .with(Cache(HttpCache {
            mode: CacheMode::Default,
            manager: CACacheManager::new("./cache".into(), true),
            options: HttpCacheOptions::default(),
        }))
        .build();
     
    // Override cache mode for this specific request
    let response = client.get("https://httpbin.org/uuid")
        .with_extension(CacheMode::OnlyIfCached) // Only serve from cache
        .send()
        .await?;
         
    // This request bypasses cache completely
    let fresh_response = client.get("https://httpbin.org/uuid")
        .with_extension(CacheMode::NoStore)
        .send()
        .await?;
         
    Ok(())
}

§Custom Cache Keys

Customize how cache keys are generated:

use reqwest::Client;
use reqwest_middleware::ClientBuilder;
use http_cache_reqwest::{Cache, CacheMode, CACacheManager, HttpCache, HttpCacheOptions};
use std::sync::Arc;

#[tokio::main]
async fn main() -> reqwest_middleware::Result<()> {
    let options = HttpCacheOptions {
        cache_key: Some(Arc::new(|req: &http::request::Parts| {
            // Include query parameters in cache key
            format!("{}:{}", req.method, req.uri)
        })),
        ..Default::default()
    };
     
    let client = ClientBuilder::new(Client::new())
        .with(Cache(HttpCache {
            mode: CacheMode::Default,
            manager: CACacheManager::new("./cache".into(), true),
            options,
        }))
        .build();
         
    Ok(())
}

§In-Memory Caching

Use the Moka in-memory cache:

use reqwest::Client;
use reqwest_middleware::ClientBuilder;
use http_cache_reqwest::{Cache, CacheMode, MokaManager, HttpCache, HttpCacheOptions};
use http_cache_reqwest::MokaCache;

#[tokio::main]
async fn main() -> reqwest_middleware::Result<()> {
    let client = ClientBuilder::new(Client::new())
        .with(Cache(HttpCache {
            mode: CacheMode::Default,
            manager: MokaManager::new(MokaCache::new(1000)), // Max 1000 entries
            options: HttpCacheOptions::default(),
        }))
        .build();
         
    Ok(())
}

Structs§

BadRequest
Error type for request parsing failure
CACacheManagermanager-cacache
Implements CacheManager with cacache as the backend.
Cache
Wrapper for HttpCache
CacheOptions
Configuration options which control behavior of the cache. Use with CachePolicy::new_options().
DirectRateLimiterrate-limiting
A direct (non-keyed) rate limiter for simple use cases where all requests share the same limit
DomainRateLimiterrate-limiting
A domain-based rate limiter using governor that limits requests per domain
HttpCache
Caches requests according to http spec.
HttpCacheOptions
Configuration options for customizing HTTP cache behavior on a per-request basis.
HttpResponse
A basic generic type that represents an HTTP response
HttpStreamingCachestreaming
Streaming version of HTTP cache that supports streaming request/response bodies without buffering them in memory.
MokaCachemanager-moka
A thread-safe, futures-aware concurrent in-memory cache.
MokaCacheBuildermanager-moka
Builds a Cache with various configuration knobs.
MokaManagermanager-moka
Implements CacheManager with moka as the backend.
Parts
Component parts of an HTTP Request
Quotarate-limiting
A rate-limiting quota.
StreamingCachestreaming
Streaming cache wrapper that implements reqwest middleware for streaming responses
StreamingManagerstreaming
File-based streaming cache manager

Enums§

CacheMode
Cache mode determines how the HTTP cache behaves for requests.
HttpCacheError
Unified error type for HTTP cache operations that works across all client libraries.
StreamingBodystreaming
A body type that can represent either buffered data from cache, streaming body from upstream, or streaming from a file for file-based caching.

Traits§

CacheAwareRateLimiterrate-limiting
A trait for rate limiting that can be implemented by different rate limiting strategies
CacheManager
A trait providing methods for storing, reading, and removing cache records.
HttpCacheStreamInterfacestreaming
Streaming version of the HTTP cache interface that supports streaming request/response bodies without buffering them in memory. This is ideal for large responses or when memory usage is a concern.

Type Aliases§

HttpCacheMetadata
Type alias for metadata stored alongside cached responses. Users are responsible for serialization/deserialization of this data.
MetadataProvider
A closure that takes http::request::Parts and http::response::Parts and returns optional metadata to store with the cached response. This allows middleware to compute and store additional information alongside cached responses.
ReqwestStreamingErrorstreaming
Type alias for reqwest streaming errors, using the unified streaming error system
ResponseCacheModeFn
A closure that takes http::request::Parts, HttpResponse and returns a CacheMode to override caching behavior based on the response