use axum::{
error_handling::HandleErrorLayer,
extract::Path,
response::{IntoResponse, Response},
routing::get,
BoxError, Router,
};
use http::StatusCode;
use http_cache::CACacheManager;
use http_cache_tower_server::ServerCacheLayer;
use tempfile::TempDir;
use tower::ServiceBuilder;
#[tokio::main]
async fn main() {
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let manager = CACacheManager::new(temp_dir.path().to_path_buf(), false);
let app = Router::new()
.route("/", get(index))
.route("/users/{id}", get(get_user))
.route("/no-cache", get(no_cache))
.layer(
ServiceBuilder::new()
.layer(HandleErrorLayer::new(handle_cache_error))
.layer(ServerCacheLayer::new(manager)),
);
let listener =
tokio::net::TcpListener::bind("127.0.0.1:3000").await.unwrap();
println!("Server running at http://localhost:3000");
println!();
println!("Try these commands:");
println!(
" curl -v http://localhost:3000/ # Watch X-Cache header"
);
println!(
" curl -v http://localhost:3000/users/42 # User-specific endpoint"
);
println!(" curl -v http://localhost:3000/no-cache # Never cached");
axum::serve(listener, app).await.unwrap();
}
async fn handle_cache_error(err: BoxError) -> Response {
(StatusCode::INTERNAL_SERVER_ERROR, format!("Cache error: {}", err))
.into_response()
}
async fn index() -> Response {
(
StatusCode::OK,
[("cache-control", "max-age=60")],
"Hello! This response is cached for 60 seconds.",
)
.into_response()
}
async fn get_user(Path(id): Path<u32>) -> Response {
(
StatusCode::OK,
[("cache-control", "max-age=30")],
format!("User {} - Cached for 30 seconds", id),
)
.into_response()
}
async fn no_cache() -> Response {
(
StatusCode::OK,
[("cache-control", "no-store")],
"This response is never cached",
)
.into_response()
}