# http-cache-tower
[](https://github.com/06chaynes/http-cache/actions/workflows/http-cache-tower.yml)
[](https://crates.io/crates/http-cache-tower)
[](https://docs.rs/http-cache-tower)
[](https://app.codecov.io/gh/06chaynes/http-cache)

<img class="logo" align="right" src="https://raw.githubusercontent.com/06chaynes/http-cache/main/.assets/images/http-cache_logo_bluegreen.svg" height="150px" alt="the http-cache logo">
An HTTP caching middleware for [Tower](https://github.com/tower-rs/tower) and [Hyper](https://hyper.rs/).
This crate provides Tower Layer and Service implementations that add HTTP caching capabilities to your HTTP clients and services.
## Minimum Supported Rust Version (MSRV)
1.82.0
## Install
With [cargo add](https://github.com/killercup/cargo-edit#Installation) installed :
```sh
cargo add http-cache-tower
```
## Features
The following features are available. By default `manager-cacache` is enabled.
- `manager-cacache` (default): enable [cacache](https://github.com/zkat/cacache-rs), a high-performance disk cache, backend manager.
- `manager-moka` (disabled): enable [moka](https://github.com/moka-rs/moka), a high-performance in-memory cache, backend manager.
- `streaming` (disabled): enable streaming cache support for memory-efficient handling of large responses using `StreamingManager`.
## Example
### Basic HTTP Cache
```rust
use http_cache_tower::HttpCacheLayer;
use http_cache::CACacheManager;
use tower::{ServiceBuilder, ServiceExt};
use http::{Request, Response};
use http_body_util::Full;
use bytes::Bytes;
use std::path::PathBuf;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a cache manager
let cache_manager = CACacheManager::new(PathBuf::from("./cache"), false);
// Create the cache layer
let cache_layer = HttpCacheLayer::new(cache_manager);
// Build your service stack
let service = ServiceBuilder::new()
.layer(cache_layer)
.service_fn(|_req: Request<Full<Bytes>>| async {
Ok::<_, std::convert::Infallible>(
Response::new(Full::new(Bytes::from("Hello, world!")))
)
});
// Use the service
let request = Request::builder()
.uri("https://httpbin.org/cache/300")
.body(Full::new(Bytes::new()))?;
let response = service.oneshot(request).await?;
println!("Status: {}", response.status());
Ok(())
}
```
## Streaming HTTP Cache
For large responses or when memory efficiency is important, use the streaming cache layer:
```rust
# #[cfg(feature = "streaming")]
use http_cache_tower::HttpCacheStreamingLayer;
# #[cfg(feature = "streaming")]
use http_cache::StreamingManager;
# #[cfg(feature = "streaming")]
use tower::{ServiceBuilder, ServiceExt};
# #[cfg(feature = "streaming")]
use http::{Request, Response};
# #[cfg(feature = "streaming")]
use http_body_util::Full;
# #[cfg(feature = "streaming")]
use bytes::Bytes;
use std::path::PathBuf;
# #[cfg(feature = "streaming")]
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// StreamingManager provides optimal streaming with no buffering
let streaming_manager = StreamingManager::new(PathBuf::from("./cache"));
// Create the streaming cache layer
let cache_layer = HttpCacheStreamingLayer::new(streaming_manager);
// Build your service stack
let service = ServiceBuilder::new()
.layer(cache_layer)
.service_fn(|_req: Request<Full<Bytes>>| async {
Ok::<_, std::convert::Infallible>(
Response::new(Full::new(Bytes::from("Large response data...")))
)
});
// Use the service - responses are streamed without buffering entire body
let request = Request::builder()
.uri("https://example.com/large-file")
.body(Full::new(Bytes::new()))?;
let response = service.oneshot(request).await?;
println!("Status: {}", response.status());
Ok(())
}
# #[cfg(not(feature = "streaming"))]
# fn main() {}
```
**Note**: For memory-efficient streaming of large responses, use `StreamingManager` with `HttpCacheStreamingLayer`. For traditional caching with smaller responses, use `CACacheManager` or `MokaManager` with `HttpCacheLayer`.
## Cache Backends
This crate supports multiple cache backends through feature flags:
- `manager-cacache` (default): Disk-based caching using [cacache](https://github.com/zkat/cacache-rs)
- `manager-moka`: In-memory caching using [moka](https://github.com/moka-rs/moka)
## Integration with Hyper Client
```rust
use http_cache_tower::HttpCacheLayer;
use http_cache::CACacheManager;
use hyper_util::client::legacy::Client;
use hyper_util::rt::TokioExecutor;
use tower::{ServiceBuilder, ServiceExt};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let cache_manager = CACacheManager::default();
let cache_layer = HttpCacheLayer::new(cache_manager);
let client = Client::builder(TokioExecutor::new()).build_http();
let cached_client = ServiceBuilder::new()
.layer(cache_layer)
.service(client);
// Now use cached_client for HTTP requests
Ok(())
}
```
## Documentation
- [API Docs](https://docs.rs/http-cache-tower)
## License
Licensed under either of
- Apache License, Version 2.0
([LICENSE-APACHE](LICENSE-APACHE) or <http://www.apache.org/licenses/LICENSE-2.0>)
- MIT license
([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
at your option.