HTTP Caching
Most important commands to remember
curl --etag-save FILE— save a response validator.curl --etag-compare FILE— make a conditional request using that validator.
Commands and flags
| Command or option | Meaning |
|---|---|
mktemp / rm "$etag_file" |
Create a unique temporary file / remove only that file. |
-i / --max-time 10 |
Show response headers / limit a transfer to ten seconds. |
--etag-save / --etag-compare |
Save an ETag / send it in If-None-Match if available. |
etag_file=$(…) stores a command’s output. Quoted variable expansion passes its path as one argument. Curl is not maintaining a full HTTP response cache here.
The concepts that matter
1. A cache reuses an earlier response
An HTTP cache stores responses so a later request may avoid downloading the same representation again. A browser cache is private to a user; a shared cache can serve many users.
Reuse saves network transfer and origin work, but it must preserve the response’s rules and request context. Caching a personalized response as if it were public can expose one user’s data to another.
2. Freshness controls reuse without validation
Cache-Control: max-age describes a freshness lifetime in seconds. Age and timing determine how much freshness remains; the object does not necessarily receive a new full lifetime whenever another cache forwards it.
no-cache permits storage but requires validation before reuse. no-store tells caches not to store the response. private restricts shared-cache storage. These directives solve different problems, so their names should not be treated as interchangeable.
3. Validators ask whether the representation changed
An ETag identifies a representation version according to the server. A client can send If-None-Match with its validator. If the representation still matches for a GET, the server can answer 304 Not Modified without sending the representation body.
The client then uses its already stored body and updates relevant metadata. A 304 is not an empty replacement document. An ETag is also not necessarily a cryptographic hash or proof of content authenticity.
4. The cache key must distinguish response variants
A URL alone may not identify the same representation for every request. Vary names request headers that distinguish cache variants, such as content negotiation fields.
Authorization, cookies, methods, and cache policy also influence safe reuse. Seeing a cached response does not prove every user gets that same response. Correct caching requires both useful lifetimes and correct separation of representations.
One small example
Optional: run the commands in one Bash terminal, continuing only after temporary-file creation succeeds. The domain may or may not provide an ETag.
etag_file=$(mktemp)
curl -i --max-time 10 --etag-save "$etag_file" https://example.com/
curl -i --max-time 10 --etag-compare "$etag_file" https://example.com/
rm "$etag_file"
Inspect Cache-Control, ETag, Age, and Vary when present. The first transfer saves only the validator, not a reusable cached body. The second sends a conditional request if a validator was saved.
A 304 means the server accepted that validation condition. A 200 can mean the representation changed, no ETag was provided, or the server returned the content normally. Neither result should be invented in advance. Curl will not display an old body after 304 because this example never stored one for reuse.
The final command deletes the temporary validator. No website cache or server configuration is changed.
Keep this idea: Freshness permits reuse; validation checks an older representation; the cache key keeps variants separate.