RFC 9211
The Cache-Status HTTP Response Header Field
RFC 9211 π The Cache-Status HTTP Response Header Field
Okay bestie, here are the deets π
- Number: RFC 9211
- Title: The Cache-Status HTTP Response Header Field
- Author: M. Nottingham, Fastly π
- Category: Standards Track
- Date: June 2022
- ISSN: 2070-1721
- Obsoletes/Updates: there are no Obsoletes or Updates lines in its header π
Abstract β¨
HTTP caches keep sneaking extra header fields onto responses to explain what they did, but everyone does it their own ad hoc way π This spec gives us one standard mechanism for it that actually lines up with HTTP's caching model π¦
Status of This Memo β¨
This is the official paperwork π It's an Internet Standards Track document. It's a product of the IETF, it reflects the consensus of the IETF community, it got public review, and the IESG approved it for publication. If you want more on Internet Standards, check Section 2 of RFC 7841. For the current status, any errata, and how to send feedback, go to https://www.rfc-editor.org/info/rfc9211. π
Copyright Notice β¨
Copyright (c) 2022 IETF Trust and the persons identified as the document authors. All rights reserved. Β©οΈ
This document is covered by BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info), as they stood on the publication date. Please read those carefully, because they spell out your rights and restrictions for this document. Any Code Components pulled out of this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions, and they come without warranty as described in the Revised BSD License. βοΈ
Table of Contents πΊοΈ
1. Introduction
1.1. Notational Conventions
2. The Cache-Status HTTP Response Header Field
2.1. The hit Parameter
2.2. The fwd Parameter
2.3. The fwd-status Parameter
2.4. The ttl Parameter
2.5. The stored Parameter
2.6. The collapsed Parameter
2.7. The key Parameter
2.8. The detail Parameter
3. Examples
4. Defining New Cache-Status Parameters
5. IANA Considerations
6. Security Considerations
7. References
7.1. Normative References
7.2. Informative References
Author's Address
1. Introduction β¨
Debugging is so much easier when you know what a cache actually did π That's why HTTP caches often tack header fields onto a response explaining how they handled the request. It's useful for humans and for automated tools alike. The problem is that what these fields mean is usually unclear, and both the semantics and the syntax change from one implementation to the next π
So this spec defines a brand new HTTP response header field called Cache-Status for exactly this job, with standardized syntax and semantics π
1.1. Notational Conventions β¨
Quick caps check π€ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be read as described in BCP 14 [RFC2119] [RFC8174], but only when they're written in all capitals, just like they are here.
This document borrows some terminology from Section 3 of [STRUCTURED-FIELDS] for its syntax and parsing: List, String, Token, Integer, and Boolean. It also uses terms from [HTTP] and [HTTP-CACHING]. π§
2. The Cache-Status HTTP Response Header Field β¨
The Cache-Status HTTP response header field tells you how caches handled that response and its matching request π Its syntax follows [STRUCTURED-FIELDS].
The value is a List, and each member of that List is a cache that handled the request. The first member is the cache closest to the origin server, and the last member is the cache closest to the user. That last one could even be the user agent's own cache, if it adds a value π§
Caches decide when it makes sense to add this header field. Some add it to every response. Others only do it when they've been specifically configured to, or when the request includes a header field that switches on a debugging mode π For the related security stuff, see Section 6, and take it seriously π
Intermediaries SHOULD NOT append a Cache-Status member to responses they generate locally, even if they contain a cache. The exception is when the generated response is built from a stored response, like 304 (Not Modified) and 206 (Partial Content), which both come from a stored response. For example, a proxy that generates a 400 response because the request was malformed won't add a Cache-Status value, since the proxy made that response itself and the origin server didn't π
ββοΈ
When a cache adds its own value to Cache-Status, it SHOULD preserve the existing field value. That way, you can debug the whole chain of caches that handled the request π
Each List member names the cache that inserted it, and that identifier MUST be a String or Token. Depending on the deployment, it could be a product or service name (like "ExampleCache" or "Example CDN"), a hostname ("cache-3.example.com"), an IP address, or a generated string π·οΈ
Each member can also carry parameters describing how that cache handled the request. Those parameters are OPTIONAL, but caches are encouraged to share as much info as they can π
Here are the parameters this specification defines β¨
2.1. The hit Parameter
The hit parameter is a Boolean. When it's true, it means the cache satisfied the request. In other words, the request wasn't forwarded, and the response came straight from the cache π―
A response the origin originally produced, but the cache modified (say, a 304 or 206 status code), still counts as a hit, as long as the request didn't go forward, for example for validation β
A response that was sitting in the cache but couldn't be used without going forward (because it was stale or partial) does NOT count as a hit π Heads up, though: a stale response that gets used without going forward (say, because the origin server is down) can count as a hit π€·ββοΈ
hit and fwd are mutually exclusive. Only one of them should show up on each List member.
2.2. The fwd Parameter
fwd, when it's there, tells you the request went forward toward the origin. Its value is a Token that explains why π
These are the values defined to explain why the request went forward, from most specific to least specific:
bypass: the cache was set up to not handle this request at all πmethod: the request method's semantics mean the request has to be forwarded.uri-miss: the cache didn't have any responses matching the request URI.vary-miss: the cache had a response matching the request URI, but it couldn't pick one based on this request's header fields and the stored Vary header fields.miss: the cache didn't have any responses that could satisfy this request. Use this when an implementation can't telluri-missandvary-missapart.request: the cache could pick a fresh response, but the request's semantics (like Cache-Control request directives) didn't allow using it π€stale: the cache could pick a response for the request, but it was stale π₯partial: the cache could pick a partial response for the request, but it didn't have all the ranges that were requested (or the request was for the complete response) π§©
The most specific reason the cache knows SHOULD be used, as far as it's possible to implement. See also Section 4 of [HTTP-CACHING].
2.3. The fwd-status Parameter
The fwd-status parameter is an Integer that tells you which status code (see Section 15 of [HTTP]) the next-hop server sent back for the forwarded request π¨ It only means something when fwd is present. If fwd-status isn't there but fwd is, it defaults to the status code sent in the response.
This one's handy for telling apart a next-hop server sending a 304 (Not Modified) for a conditional request from a next-hop server sending a 206 (Partial Content) because of a range request π΅οΈββοΈ
2.4. The ttl Parameter
The ttl parameter is an Integer showing how much freshness lifetime the response has left (see Section 4.2.1 of [HTTP-CACHING]), as the cache calculated it. It's an integer number of seconds, measured as close as possible to when the cache sends the response header section β³ That includes freshness the cache gave the response itself through things like heuristics (see Section 4.2.2 of [HTTP-CACHING]), local configuration, or other factors. It may be negative, which means the response is stale π΅βπ«
2.5. The stored Parameter
The stored parameter is a Boolean that says whether the cache stored the response (see Section 3 of [HTTP-CACHING]). A true value means it did πΎ This parameter only means something when fwd is present.
2.6. The collapsed Parameter
The collapsed parameter is a Boolean that says whether this request got collapsed together with one or more other forward requests (see Section 4 of [HTTP-CACHING]) π«§ If it's true, the response was successfully reused. If it's false, a new request had to be made. If it isn't present at all, the request wasn't collapsed with any others. This parameter only means something when fwd is present.
2.7. The key Parameter
The key parameter is a String that represents the cache key (see Section 2 of [HTTP-CACHING]) used for the response π Heads up that this may be implementation specific.
2.8. The detail Parameter
The detail parameter is either a String or a Token. It lets implementations pass along extra info that the other parameters don't cover, like implementation-specific states or other caching-related metrics π
For example:
Cache-Status: ExampleCache; hit; detail=MEMORY
A detail parameter only means something to the cache that sent it. Even if a detail parameter from a different cache has the same value, it might not mean the same thing π
This parameter is intentionally limited π«£ If an implementation's developer or operator needs to share extra info in an interoperable way, they're encouraged to register extension parameters (see Section 4) or define another header field entirely π
3. Examples β¨
okay bestie, let's look at some examples π first up is the most minimal cache hit ever:
Cache-Status: ExampleCache; hit
but a polite cache will give you a bit more info, like this π«Ά
Cache-Status: ExampleCache; hit; ttl=376
a stale hit just has negative freshness, like this one π₯
Cache-Status: ExampleCache; hit; ttl=-412
whereas this is a complete miss π
Cache-Status: ExampleCache; fwd=uri-miss
this is a miss that successfully validated on the backend server, and it's giving main character energy π
Cache-Status: ExampleCache; fwd=stale; fwd-status=304
this is a miss that got collapsed with another request, which is so efficient π§
Cache-Status: ExampleCache; fwd=uri-miss; collapsed
this is a miss where the cache tried to collapse the request but couldn't. ngl that's a sad little story π
Cache-Status: ExampleCache; fwd=uri-miss; collapsed=?0
now for the layered stuff, which is my favourite part π this one is two separate caching layers. the cache closest to the origin already answered an earlier request with a stored response, and then a second cache stored that response and reused it later to satisfy the current request. two caches, one response, zero drama β¨
Cache-Status: OriginCache; hit; ttl=1100,
"CDN Company Here"; hit; ttl=545
and this is a three-layer caching system, which is honestly iconic π the one closest to the origin is a reverse proxy, and the response came from its cache. next up is a forward proxy that the network put in the middle. it forwarded the request because nothing was cached for that URI, the request got collapsed with others, and the resulting response was stored. last is the browser cache, closest to the user, where nothing was cached for the request's URI
Cache-Status: ReverseProxyCache; hit
Cache-Status: ForwardProxyCache; fwd=uri-miss; collapsed; stored
Cache-Status: BrowserCache; fwd=uri-miss
4. Defining New Cache-Status Parameters π¦
okay so if you want to make a brand new Cache-Status parameter, you register it in the "HTTP Cache-Status" registry π
registration requests get reviewed and approved by a designated expert, per [RFC8126], Section 4.5. a specification document is appreciated but not required, so you don't have to write one, but it's a very nice thing to do πΈ
the expert(s) should think about these factors when they evaluate requests:
- Community feedback
- If the value is sufficiently well defined
- Generic parameters are preferred over vendor-specific, application-specific, or deployment-specific values. If a generic value cannot be agreed upon in the community, the parameter's name should be correspondingly specific (e.g., with a prefix that identifies the vendor, application, or deployment).
registration requests should use the following template, no skipping the boring bits π
Name: [a name for the Cache-Status parameter's key; see
Section 3.1.2 of [STRUCTURED-FIELDS] for syntactic requirements]
Type: [the Structured Type of the parameter's value; see
Section 3.1.2 of [STRUCTURED-FIELDS]]
Description: [a description of the parameter's semantics]
Reference: [to a specification defining this parameter, if
available]
see the registry at https://www.iana.org/assignments/http-cache-status for details on where to send registration requests π
5. IANA Considerations π
IANA has created the "HTTP Cache-Status" registry at https://www.iana.org/assignments/http-cache-status and populated it with the types defined in Section 2. see Section 4 for its associated procedures π
IANA also added the following entry in the "Hypertext Transfer Protocol (HTTP) Field Name Registry", which is defined in [HTTP], Section 18.4 β¨
Field name: Cache-Status
Status: permanent
Reference: RFC 9211
6. Security Considerations π
okay this section is serious, bestie, so pay attention π₯Ί attackers can use the information in Cache-Status to probe how the cache (and other components) behave, and then infer what the people using the cache are doing. the Cache-Status header field may not create these risks on its own, but it can help attackers exploit them π±
for example, knowing whether a cache has stored a response can help an attacker run a timing attack on sensitive data. yikes π
also, exposing the cache key can help an attacker understand changes to the cache key, which may help with cache poisoning attacks. see [ENTANGLE] for details π·οΈ
the underlying risks can be mitigated with a bunch of techniques, like encryption and authentication and not putting attacker-controlled data in the cache key. which one you need depends on the exact nature of the risk. and note that merely obfuscating the key does not mitigate this risk. you can't just hide it and call it a day π ββοΈ
to avoid helping these attacks, you can omit the Cache-Status header field, only send it when the client is authorized to receive it, or send sensitive information (e.g., the key parameter) only when the client is authorized. protect your bestie's data, periodt π
7. References π
7.1. Normative References
- [HTTP] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., "HTTP Semantics", STD 97, RFC 9110, DOI 10.17487/RFC9110, June 2022,
https://www.rfc-editor.org/info/rfc9110. - [HTTP-CACHING] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., "HTTP Caching", STD 98, RFC 9111, DOI 10.17487/RFC9111, June 2022,
https://www.rfc-editor.org/info/rfc9111. - [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997,
https://www.rfc-editor.org/info/rfc2119. - [RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 8126, DOI 10.17487/RFC8126, June 2017,
https://www.rfc-editor.org/info/rfc8126. - [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017,
https://www.rfc-editor.org/info/rfc8174. - [STRUCTURED-FIELDS] Nottingham, M. and P-H. Kamp, "Structured Field Values for HTTP", RFC 8941, DOI 10.17487/RFC8941, February 2021,
https://www.rfc-editor.org/info/rfc8941.
7.2. Informative References
- [ENTANGLE] Kettle, J., "Web Cache Entanglement: Novel Pathways to Poisoning", September 2020,
https://portswigger.net/research/web-cache-entanglement.
Author's Address πΈ
Mark Nottingham
Fastly
Prahran
Australia
Email: mnot@mnot.net
URI: https://www.mnot.net/
that's the whole doc, bestie! ππ you made it through the Cache-Status spec π
π¦ where this page comes from
- ietf: rfc9211 2022-06
- π girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms