http-cache 1.0.0-alpha.7

An HTTP caching middleware
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
# Changelog

## [1.0.0-alpha.7] - 2026-07-22

### Added

- `RedbManager` cache backend using redb for persistent, synchronous on-disk caching that requires no async runtime
- `manager-redb` feature flag for enabling `RedbManager`
- `StreamingCacheManager::update_metadata` for refreshing a stored entry's headers, policy, and user metadata without touching the body file. This is a required method, so existing implementations of the trait must add it.
- `CachedRequestMethod` and `CacheEntryToken` response extensions, used by the streaming orchestrator to tell a manager which request method produced a response and which stored entry a cached response was served from

### Changed

- MSRV bumped from 1.88.0 to 1.89.0
- Default cache manager changed from `manager-cacache` to `manager-redb`. `manager-cacache` (and `CACacheManager`) is now opt-in — enable the `manager-cacache` feature to keep using it. The `cacache` crate is no longer maintained upstream.
- `RedbManager` holds an exclusive file lock on its database: a second manager (or process) opening the same path fails at construction. Share one instance via `Arc` instead. This differs from the previous default `CACacheManager`, which allowed concurrent access to one cache directory.
- `RedbManager` stores are batched for durability: commits are flushed to disk every 64 writes (configurable via `from_database_with_flush_interval`) and on drop, so a crash can lose approximately the most recent 64 stores. Deletes commit durably, so invalidations survive a crash.
- `StreamingManager` metadata now includes a blake3 body checksum, verified while streaming; corrupt entries error the stream and self-heal to a miss. Existing streaming cache entries from earlier alphas fail to decode and are treated as misses (re-fetched once).
- `StreamingBody::from_file_with_size` now streams exactly `size` bytes and errors on a shorter file; it previously read to end of file, treating `size` as a hint.
- `StreamingManager` no longer prewarms its in-memory metadata cache at startup; hydration is lazy, so `entry_count()` reads 0 after a restart until keys are accessed.
- Non-cacheable responses on the streaming path are now passed through without buffering (`StreamingManager::Body` is `StreamingBody<UnsyncBoxBody<Bytes, StreamingError>>`). Upstream body failures on that path surface as stream errors while the body is read, not as a middleware error before the response is returned.
- Concurrent operations on the same cache key in `StreamingManager` are serialized with per-key locks, so racing gets/puts can no longer drop freshly written entries.
- `StreamingManager::put` writes the response body to disk one frame at a time instead of collecting it into memory first, so peak memory no longer scales with response size. It returns a body backed by the committed on-disk entry rather than an in-memory copy.
- Responses larger than `max_body_size` are no longer an error: caching is declined and the response is served in full, uncached. A declared `Content-Length` over the limit skips writing to disk entirely. HEAD responses are exempt, since their `Content-Length` describes the entity rather than the empty body.
- Responses whose received length does not match their declared `Content-Length` are served but not cached, so a truncated response is never stored (RFC 9111 s3.3). HEAD responses are exempt.
- Hop-by-hop headers are no longer written into cached entries. This covers `connection`, `transfer-encoding`, the rest of the RFC 9111 s3.1 set, and any field names listed in a `Connection` header. Live responses are unaffected.
- 304 revalidation on the streaming path updates the stored metadata in place instead of re-reading and rewriting the body file, so revalidating a large entry no longer costs a full read and write.
- `StreamingCacheManager::put` documents when a stored entry becomes visible: at or after the returned body has been fully consumed. The bundled `StreamingManager` makes it visible before `put` returns, but implementations are not required to.

## [1.0.0-alpha.6] - 2026-04-17

### Added

- `HttpStreamingCache::run` orchestrator for streaming cache operations, eliminating duplicated logic in downstream middleware crates
- `FetchRequest` enum for callback-based fetch dispatch in streaming paths
- `run_no_cache_from_parts` public method on `HttpCache` for cache-busting with pre-extracted request parts
- `CachedUserMetadata` for preserving user metadata through 304 re-cache operations
- `response_cache_mode_fn` evaluation in `conditional_fetch` 200 branch (both paths)

### Changed

- `StreamingManager` storage backend replaced with an embedded `redb` database (for metadata) plus raw `tokio::fs` files (for response bodies), fronted by `moka` as an in-memory hot cache. This replaces the previous `cacache`-based backend. Overwrites atomically replace prior content; there is no longer any background eviction-driven disk cleanup. Disk state is managed explicitly by `put`, `delete`, and `clear`. The on-disk format is not compatible with previous releases — users upgrading should delete the `metadata.redb` file, the `bodies/` subdirectory, and the `tmp/` subdirectory from their cache directory before the first run on this version.
- Only one `StreamingManager` instance may point at a given cache directory at a time (enforced via the database file lock on `metadata.redb`). Attempting to construct a second instance while another is alive returns an error.
- `StreamingManager::entry_count()` now returns the count of entries currently warm in the in-memory hot cache, not the total number of entries persisted on disk. When the cache has fewer entries than the configured capacity, this equals the previous value; once capacity is exceeded, cold entries remain reachable via `get` but are not counted here.
- Replaced `async_trait` with native async functions in traits (RPITIT) for `CacheManager`, `StreamingCacheManager`, and `Middleware` traits
- `CacheAwareRateLimiter::until_key_ready` now returns `Pin<Box<dyn Future>>` for dyn-compatibility
- Removed `async-trait` dependency
- Cache deserialization failure logs lowered from `warn` to `debug` level
- `modify_response_before_caching` is now `pub` on `HttpCacheOptions`

### Fixed

- `StreamingManager` now persists cache entries across service restarts (#159). Previously the key→content mapping was only kept in memory, so cached bodies on disk became unreachable orphans after restart.
- Multi-valued response headers (e.g. `Set-Cookie`, `Via`, `Link`) are now preserved correctly when merging headers from revalidation responses. Previously `HttpResponse::update_headers`, the streaming `conditional_fetch` Fresh/304 merges, and the streaming `handle_not_modified` path all lost or duplicated values for same-named headers.
- RFC 7234 s4.4: cache invalidation now gated on successful response status (2xx/3xx) for unsafe methods
- RFC 7234 s4.4: HEAD cache entries now invalidated alongside GET entries
- `conditional_fetch` 200 branch now checks `should_cache_response` before caching
- Streaming path now respects `matches` flag from `BeforeRequest::Stale`
- Streaming path now handles all cache modes (NoCache, ForceCache, OnlyIfCached, IgnoreRules)
- Streaming 304 path preserves original user metadata instead of regenerating
- `modify_response_before_caching` now called at correct point in streaming cache paths
- Cache status headers set in correct order relative to `modify_response` and `manager.put`
- Warning header cleanup (1xx removal) on cached responses in streaming path
- 5xx stale fallback with Warning 111 in streaming conditional fetch
- `OnlyIfCached` 504 body now empty (consistent between streaming and non-streaming)

## [1.0.0-alpha.5] - 2026-02-17

### Added

- `url-standard` feature flag as the new default URL implementation using the `url` crate
- Transparent bincode-to-postcard migration in `CACacheManager` and `MokaManager` (reads legacy bincode data, writes postcard)

### Changed

- `StreamingManager` rewritten to use cacache for disk storage with moka for metadata tracking and TinyLFU eviction
- MSRV bumped from 1.85.0 to 1.88.0
- Updated `http-cache-semantics` from 2.1.0 to 3.0.0
- Updated `foyer` to 0.22.3
- Updated `rand` to 0.10.0
- `url` crate is now optional behind `url-standard` feature (enabled by default)
- Removed `runtime` module, streaming no longer requires runtime-specific code

### Fixed

- Metadata handling with bincode serialization
- `CacheMode` enum variant matching logic
- Feature flag gates for doc tests

## [1.0.0-alpha.4] - 2026-01-19

### Added

- `empty_body` method to `StreamingCacheManager` trait for creating empty body responses
- `get_ref_count` method to `ContentRefCounter` for non-mutating reference count checks
- `FoyerManager` cache backend using foyer for hybrid in-memory and disk caching
- `manager-foyer` feature flag for enabling `FoyerManager`
- `manager-cacache-bincode` and `manager-moka-bincode` feature flags for legacy bincode serialization
- `url-ada` feature flag for using WHATWG-compliant ada-url as an alternative to the url crate
- `url_parse`, `url_set_path`, `url_set_query`, `url_hostname`, `url_host_str` helper functions for URL operations

### Changed

- `StreamingManager` now wraps `ContentRefCounter` in `Arc` to ensure all clones share the same state
- Atomic operations in streaming cache now use proper memory ordering (`Acquire`/`Release`/`AcqRel`) instead of `Relaxed`
- Default serialization format changed from bincode to postcard (cache data incompatible with previous versions)
- Removed `cacache-smol` and `cacache-tokio` features in favor of tokio-only runtime
- `cacache` dependency now uses `tokio-runtime` by default
- Removed async-std from dependency tree

### Fixed

- Race condition in `remove_ref` using atomic `compare_exchange` loop to prevent TOCTOU bugs
- Cache size and entry count divergence when `StreamingManager` is cloned
- Memory leak in `delete` where reference count was decremented but not restored on non-orphaned content
- Race condition in `delete` by using non-mutating `get_ref_count` instead of remove/add pattern

## [1.0.0-alpha.3] - 2026-01-18

### Added

- `modify_response` field to `HttpCacheOptions` for modifying responses before storing in cache
- `http-headers-compat` feature flag for header compatibility options
- `metadata` field to `HttpResponse` for storing arbitrary data with cached responses
- `metadata_provider` function to `HttpCacheOptions` for computing metadata on cache store

### Changed

- MSRV is now 1.85.0

### Fixed

- Serialize all header values instead of just the first value per header name
- `HttpHeaders` serialization and insert behavior for bincode compatibility
- Preserve all header values sharing the same name

## [1.0.0-alpha.2] - 2025-08-24

### Added

- `max_ttl` field to `HttpCacheOptions` for controlling maximum cache duration
- Support for `Duration` type in `max_ttl` field for better ergonomics and type safety
- Cache duration limiting functionality that overrides longer server-specified durations while respecting shorter ones
- Enhanced cache expiration control for `CacheMode::IgnoreRules` mode
- `rate_limiter` field to `HttpCacheOptions` for cache-aware rate limiting that only applies on cache misses
- `CacheAwareRateLimiter` trait for implementing rate limiting strategies
- `DomainRateLimiter` for per-domain rate limiting using governor
- `DirectRateLimiter` for global rate limiting using governor
- New `rate-limiting` feature flag for optional rate limiting functionality
- Rate limiting support for streaming cache operations with seamless integration
- Simple LRU eviction policy for the `StreamingManager` with configurable size and entry limits
- Multi-runtime async support (tokio/smol) with `RwLock` for better async performance
- Content deduplication using Blake3 hashing for efficient storage
- Atomic file operations using temporary files and rename for safe concurrent access
- Configurable streaming buffer size for optimal streaming performance
- Lock-free reference counting using DashMap for concurrent access
- LRU cache implementation using the `lru` crate

### Changed

- `max_ttl` implementation automatically enforces cache duration limits by modifying response cache-control headers
- Documentation updated with comprehensive examples for `max_ttl` usage across all cache modes
- `StreamingCacheConfig` simplified to essential configuration options:
  - `max_cache_size`: Optional cache size limit for LRU eviction
  - `max_entries`: Optional entry count limit for LRU eviction  
  - `streaming_buffer_size`: Buffer size for streaming operations (default: 8192)
- Enhanced error types and handling for streaming cache operations
- Simplified `StreamingManager` implementation focused on core functionality and maintainability
- Removed unused background cleanup and persistent reference counting infrastructure for cleaner codebase
- Improved async compatibility across tokio and smol runtimes
- Upgraded concurrent data structures to use DashMap and LRU cache
- Replaced custom implementations with established library solutions

### Fixed

- Race conditions in reference counting during concurrent access
- Resource leaks in streaming cache operations when metadata write fails
- Unsafe unwrap operations in cache entry manipulation
- Inefficient URL construction replaced with safer url crate methods
- Improved error handling and recovery in streaming operations

## [1.0.0-alpha.1] - 2025-07-27

### Added

- New streaming cache architecture for handling large HTTP responses without buffering entirely in memory
- `StreamingCacheManager` trait for streaming-aware cache backends
- `HttpCacheStreamInterface` trait for composable streaming middleware patterns
- `HttpStreamingCache` struct for managing streaming cache operations
- `StreamingManager` implementation using file-based storage
- `StreamingBody` type for handling both buffered and streaming scenarios
- `CacheAnalysis` struct for better separation of cache decision logic
- `response_cache_mode_fn` field to `HttpCacheOptions` for per-response cache mode overrides
- New streaming feature flags: `streaming`, `streaming-tokio`, `streaming-smol`

### Changed

- Refactored `Middleware` trait for better composability
- Cache manager interfaces now support both buffered and streaming operations
- Enhanced separation of concerns with discrete analysis/lookup/processing steps
- Renamed `cacache-async-std` feature to `cacache-smol` for consistency
- MSRV updated to 1.82.0

## [0.21.0] - 2025-06-25

### Added

- `remove_opts` field to `CACacheManager` struct. This field is an instance of `cacache::RemoveOpts` that allows for customization of the removal options when deleting items from the cache.

- MSRV is now 1.82.0

## [0.20.1] - 2025-01-30

### Changed

- Fixed missing implementation of CacheMode::Reload variant logic.

- MSRV is now 1.81.1

- Updated the minimum versions of the following dependencies:
  - async-trait [0.1.85]
  - cacache [13.1.0]
  - httpdate [1.0.2]
  - moka [0.12.10]
  - serde [1.0.217]
  - url [2.5.4]

## [0.20.0] - 2024-11-12

### Added

- `cache_status_headers` field to `HttpCacheOptions` struct. This field is a boolean that determines if the cache status headers should be added to the response.

## [0.19.0] - 2024-04-10

### Changed

- Updated the minimum versions of the following dependencies:
  - cacache [13.0.0]
  - http [1.1.0]
  - http-cache-semantics [2.1.0]

## [0.18.0] - 2024-01-15

### Added

- `overridden_cache_mode` method to `Middleware` trait. This method allows for overriding any cache mode set in the configuration, including `cache_mode_fn`.

- Derive `Default` for the `CacheMode` enum with the mode `Default` selected to be used.

## [0.17.0] - 2023-11-01

### Added

- `cache_mode_fn` field to `HttpCacheOptions` struct. This is a closure that takes a `&http::request::Parts` and returns a `CacheMode` enum variant. This allows for the overriding of cache mode on a per-request basis.

- `cache_bust` field to `HttpCacheOptions` struct. This is a closure that takes `http::request::Parts`, `Option<CacheKey>`, the default cache key (`&str`) and returns `Vec<String>` of keys to bust the cache for.

### Changed

- Updated the minimum versions of the following dependencies:
  - cacache [12.0.0]

## [0.16.0] - 2023-09-28

### Added

- `can_cache_request` method to `HttpCache` struct. This can be used by client implementations to determine if the request should be cached.

- `run_no_cache` method to `HttpCache` struct. This should be run by client implementations if the request is determined to not be cached.

### Changed

- MSRV is now 1.67.1

## [0.15.0] - 2023-09-26

### Added

- `IgnoreRules` variant to the `CacheMode` enum. This mode will ignore the HTTP headers and always store a response given it was a 200 response. It will also ignore the staleness when retrieving a response from the cache, so expiration of the cached response will need to be handled manually. If there was no cached response it will create a normal request, and will update the cache with the response.

### Changed

- Updated the minimum versions of the following dependencies:
  - moka [0.12.0]

## [0.14.0] - 2023-07-28

### Added

- `cacache-async-std` feature, which enables `async_std` runtime support in the `cacache` backend manager. This feature is enabled by default.

- `cacache-tokio` feature, which enables `tokio` runtime support in the `cacache` backend manager. This feature is disabled by default.

### Changed

- Updated the minimum versions of the following dependencies:
  - async-std [1.12.0]
  - async-trait [0.1.72]
  - serde [1.0.178]
  - tokio [1.29.1]

## [0.13.0] - 2023-07-19

### Added

- `CacheKey` type, a closure that takes [`http::request::Parts`] and returns a [`String`].

- `HttpCacheOptions` struct that contains the cache key (`CacheKey`) and the cache options (`CacheOptions`).

### Changed

- `CacheManager` trait `get`, `put`, and `delete` methods now require a `cache_key` argument rather than `method` and `url` arguments. This allows for custom keys to be specified.

- Both the `CACacheManager` trait and `MokaManager` implementation have been updated to reflect the above change.

- Updated the minimum versions of the following dependencies:
  - async-trait [0.1.71]
  - moka [0.11.2]
  - serde [1.0.171]

## [0.12.0] - 2023-06-05

### Changed

- MSRV is now 1.66.1
- `CACacheManager` field `path` has changed to `std::path::PathBuf`

- Updated the minimum versions of the following dependencies:
  - cacache [11.6.0]
  - moka [0.11.1]
  - serde [1.0.163]
  - url [2.4.0]

## [0.11.0] - 2023-03-29

### Added

- `BoxError` type alias for `Box<dyn std::error::Error + Send + Sync>`.

- `BadVersion` error type for unknown http versions.

- `BadHeader` error type for bad http header values.

### Removed

- `CacheError` enum.

- The following dependencies:
  - anyhow
  - thiserror
  - miette

### Changed

- `CacheError` enum has been replaced in function by `Box<dyn std::error::Error + Send + Sync>`.

- `Result` typedef is now `std::result::Result<T, BoxError>`.

- `Error` type for the TryFrom implentation for the `HttpVersion` struct is now `BoxError` containing a `BadVersion` error.

- `CacheManager` trait `put` method now returns `Result<(), BoxError>`.

- Updated the minimum versions of the following dependencies:
  - async-trait [0.1.68]
  - cacache [11.4.0]
  - moka [0.10.1]
  - serde [1.0.159]

## [0.10.1] - 2023-03-08

### Changed

- Set conditional check for `CacheError::Bincode` to `cfg(feature = "bincode")`

## [0.10.0] - 2023-03-08

### Changed

- MSRV is now 1.63.0

- Updated the minimum versions of the following dependencies:
  - async-trait [0.1.66]
  - cacache [11.3.0]
  - serde [1.0.154]
  - thiserror [1.0.39]

## [0.9.2] - 2023-02-23

### Changed

- Updated the minimum versions of the following dependencies:
  - cacache [11.1.0]

## [0.9.1] - 2023-02-17

### Changed

- Updated the minimum versions of the following dependencies:
  - http [0.2.9]

## [0.9.0] - 2023-02-16

### Changed

- MSRV is now 1.62.1

- Updated the minimum versions of the following dependencies:
  - moka [0.10.0]

## [0.8.0] - 2023-02-07

### Changed

- MSRV is now 1.60.0

- Updated the minimum versions of the following dependencies:
  - anyhow [1.0.69]
  - async-trait [0.1.64]
  - cacache [11.0.0]
  - miette [5.5.0]
  - moka [0.9.7]
  - serde [1.0.152]
  - thiserror [1.0.38]

## [0.7.2] - 2022-11-16

- Added derive `Eq` to `HttpVersion` enum.

### Changed

## [0.7.1] - 2022-11-06

### Changed

- Updated the minimum versions of the following dependencies:
  - anyhow [1.0.66]
  - async-trait [0.1.58]
  - miette [5.4.1]
  - moka [0.9.6]
  - serde [1.0.147]
  - thiserror [1.0.37]
  - url [2.3.1]

## [0.7.0] - 2022-06-17

### Changed

- The `CacheManager` trait is now implemented directly against the `MokaManager` struct rather than `Arc<MokaManager>`. The Arc is now internal to the `MokaManager` struct as part of the `cache` field.

- Updated the minimum versions of the following dependencies:
  - async-trait [0.1.56]
  - http [0.2.8]
  - miette [4.7.1]
  - moka [0.8.5]
  - serde [1.0.137]
  - thiserror [1.0.31]

## [0.6.5] - 2022-04-30

### Changed

- Updated the minimum versions of the following dependencies:
  - http [0.2.7]

## [0.6.4] - 2022-04-26

### Added

- This changelog to keep a record of notable changes to the project.