2 releases
Uses new Rust 2024
| 0.2.1 | Feb 9, 2026 |
|---|---|
| 0.2.0 | Jan 27, 2026 |
#706 in Caching
Used in 2 crates
650KB
11K
SLoC
hitbox-http
HTTP caching primitives for the Hitbox framework.
This crate provides the building blocks for caching HTTP requests and responses: predicates to determine cacheability, extractors to generate cache keys, and body utilities for transparent request/response handling.
Core Concepts
-
Predicate: Evaluates whether a request or response should be cached. Returns
CacheableorNonCacheable. -
Extractor: Generates cache key parts from HTTP components (method, path, headers, query parameters, body).
-
CacheableSubject: A trait that allows predicates and extractors to work uniformly with both requests and responses. -
BufferedBody: A body wrapper with three states (Complete,Partial,Passthrough) enabling transparent caching without disrupting the HTTP stream.
Quickstart
use std::time::Duration;
use hitbox::Config;
use hitbox::policy::PolicyConfig;
use hitbox::predicate::PredicateExt;
use hitbox_http::{
extractors::{Method, path::PathExtractor, query::QueryExtractor},
predicates::{
header::{Header, Operation as HeaderOperation},
response::StatusCode,
},
};
# use bytes::Bytes;
# use http_body_util::Empty;
// Skip cache when Cache-Control: no-cache is present
let request_predicate = Header::new(HeaderOperation::Contains(
http::header::CACHE_CONTROL,
"no-cache".to_string(),
)).not();
// Only cache successful responses
let response_predicate = StatusCode::new(http::StatusCode::OK);
// Build cache key from method, path parameters, and query
let extractor = Method::new()
.path("/users/{user_id}/posts/{post_id}")
.query("page".to_string());
// Build a cache configuration for an endpoint
let config = Config::builder()
.request_predicate(request_predicate)
.response_predicate(response_predicate)
.extractor(extractor)
.policy(PolicyConfig::builder().ttl(Duration::from_secs(300)).build())
.build();
# use hitbox::predicate::Not;
# use hitbox_http::predicates::{NeutralRequestPredicate, NeutralResponsePredicate};
# use hitbox_http::extractors::{NeutralExtractor, Path, query::Query};
# let _: Config<
# Not<Header<NeutralRequestPredicate<Empty<Bytes>>>>,
# StatusCode<NeutralResponsePredicate<Empty<Bytes>>>,
# Query<Path<Method<NeutralExtractor<Empty<Bytes>>>>>,
# > = config;
Predicates
Predicates determine whether a request or response is cacheable.
Request Predicates
| Predicate | Description |
|---|---|
predicates::request::Method |
Match by HTTP method (GET, POST, etc.) |
predicates::request::Path |
Match by path pattern |
predicates::request::Header |
Match by header presence or value |
predicates::request::Query |
Match by query parameter |
predicates::request::Body |
Match by request body content |
Response Predicates
| Predicate | Description |
|---|---|
predicates::response::StatusCode |
Match by status code or class |
predicates::response::Header |
Match by header presence or value |
predicates::response::Body |
Match by response body content |
Combining Predicates
Use PredicateExt methods to combine predicates:
use hitbox::predicate::PredicateExt;
use hitbox_http::predicates::header::{Header, Operation};
# use bytes::Bytes;
# use http_body_util::Empty;
# use hitbox::Neutral;
# use hitbox_http::CacheableHttpRequest;
# type Subject = CacheableHttpRequest<Empty<Bytes>>;
// Skip cache when Cache-Control contains "no-cache"
let skip_no_cache = Header::new(Operation::Contains(
http::header::CACHE_CONTROL,
"no-cache".to_string(),
));
# let _: &Header<Neutral<Subject>> = &skip_no_cache;
let skip_no_cache = skip_no_cache.not();
// Skip cache when Authorization header exists
let skip_auth = Header::new(Operation::Exist(
http::header::AUTHORIZATION,
)).not();
// Combine: cache only if BOTH conditions pass
let combined = skip_no_cache.and(skip_auth);
Extractors
Extractors generate cache key parts from HTTP components. Chain them using the builder pattern:
use hitbox_http::extractors::{Method, path::PathExtractor, query::QueryExtractor};
# use bytes::Bytes;
# use http_body_util::Empty;
# use hitbox_http::extractors::{NeutralExtractor, Path, query::Query};
let extractor = Method::new()
.path("/users/{user_id}")
.query("page".to_string())
.query("limit".to_string());
# let _: Query<Query<Path<Method<NeutralExtractor<Empty<Bytes>>>>>> = extractor;
| Extractor | Description |
|---|---|
extractors::Method |
Extract HTTP method |
extractors::Path |
Extract path parameters using patterns like /users/{id} |
extractors::header |
Extract header values |
extractors::query |
Extract query parameters |
extractors::body |
Extract from body (hash, JQ, regex) |
extractors::Version |
Extract HTTP version |
Main Types
CacheableHttpRequest: Wraps an HTTP request for cache evaluation.CacheableHttpResponse: Wraps an HTTP response for cache storage.SerializableHttpResponse: Serialized form of a response for cache backends.
Feature Flags
rkyv_format: Enables zero-copy deserialization using rkyv.
Dependencies
~43MB
~753K SLoC