http-fresh
HTTP response freshness (conditional GET) checking for Rust.
Decide whether a cached response is still fresh for a request — i.e. whether your
server may answer 304 Not Modified instead of resending the body. http-fresh
evaluates the If-None-Match / If-Modified-Since request headers against the
response's ETag / Last-Modified, honoring Cache-Control: no-cache.
It is a faithful Rust port of the widely-used fresh
npm package (the logic behind Express's req.fresh), which has no Rust equivalent.
- Zero dependencies
#![no_std]— works anywherecoredoes- Zero heap allocation — no
allocrequired - Differential-tested against the reference
freshimplementation
Install
[]
= "0.1"
Usage
use ;
// ETag-based conditional GET.
let req = new.if_none_match;
let res = new.etag;
assert!; // matching ETag → fresh → send 304
let res = new.etag;
assert!; // changed → stale → send the body
// Date-based conditional GET.
let req = new.if_modified_since;
let res = new.last_modified;
assert!; // not modified since → fresh
// Cache-Control: no-cache always forces a revalidation.
let req = req.cache_control;
assert!;
You can also build the headers as plain struct literals (all fields are Option<&str>
and default to None):
use ;
let req = Request ;
let res = Response ;
assert!;
Semantics
fresh returns true (the response is fresh — send 304) only when:
- The request is conditional (has
If-None-Matchand/orIf-Modified-Since); an unconditional request is never fresh. Cache-Control: no-cacheis not present (it always forces stale).- If
If-None-Matchis present and not*, the responseETagmatches one of its entries, using weak/strong (W/) comparison. - If
If-Modified-Sinceis present, the responseLast-Modifiedis no newer than it.
Empty-string headers are treated as absent.
Differences from the npm package
The npm package parses dates with JavaScript's Date.parse, which is lenient and — for
timezone-less formats such as asctime — interprets them in the host machine's local
timezone, so its result is not reproducible across machines. http-fresh instead parses
exactly the three date formats mandated by
RFC 9110 §5.6.7 — IMF-fixdate,
obsolete RFC 850, and asctime — always in GMT. Any string outside those formats is
treated as unparseable, which makes the response stale (a safe, revalidating default).
For real-world HTTP traffic, which uses IMF-fixdate, the behavior is identical.
Contributors ✨
This project follows the all-contributors specification. Contributions of any kind are welcome — code, docs, bug reports, ideas, reviews! See the emoji key for how each contribution is recognized, and open a PR or issue to get involved.
Thanks goes to these wonderful people:
License
Licensed under either of MIT or Apache-2.0 at your option.