RFC 8246

HTTP Immutable Responses

πŸ“… published September 2017, from ietf

RFC 8246: HTTP Immutable Responses πŸ¦‹

Okay bestie, the title block tea β˜•: this is a Standards Track doc from September 2017, ISSN 2070-1721, written by Patrick McManus from Mozilla πŸ’œ. It's an Internet Standards Track document, so this is the real deal. The title block doesn't list anything it obsoletes or updates, so it's standing on its own ✨.

Abstract ✨

The big idea is the immutable response Cache-Control extension. It lets servers flag resources that won't change during their freshness lifetime. So a client never has to revalidate a cached fresh resource just to be sure it hasn't been modified. Main character energy πŸ’…

Status of This Memo πŸ“œ

This is an Internet Standards Track document.

This doc is a product of the Internet Engineering Task Force (IETF) 🌈 It represents the consensus of the IETF community, got public review, and was approved for publication by the Internet Engineering Steering Group (IESG). For 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/rfc8246 πŸ”—

Copyright (c) 2017 IETF Trust and the persons identified as the document authors. All rights reserved.

This doc is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) as in effect on the date of publication. Please read those carefully, because they spell out your rights and restrictions for this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions, and they're provided without warranty as described in the Simplified BSD License.

Table of Contents πŸ—‚οΈ

1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   2
  1.1.  Notational Conventions  . . . . . . . . . . . . . . . . .   3
2.  The Immutable Cache-Control Extension . . . . . . . . . . . .   3
  2.1.  About Intermediaries  . . . . . . . . . . . . . . . . . .   4
  2.2.  Example . . . . . . . . . . . . . . . . . . . . . . . . .   4
3.  Security Considerations . . . . . . . . . . . . . . . . . . .   4
4.  IANA Considerations . . . . . . . . . . . . . . . . . . . . .   5
5.  References  . . . . . . . . . . . . . . . . . . . . . . . . .   5
  5.1.  Normative References  . . . . . . . . . . . . . . . . . .   5
  5.2.  Informative References  . . . . . . . . . . . . . . . . .   5
Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . .   6
Author's Address  . . . . . . . . . . . . . . . . . . . . . . . .   6

1. Introduction 🌸

Okay so HTTP's freshness lifetime mechanism [RFC7234] lets a client safely reuse a stored response to answer future requests for a set amount of time. The catch is that the resource can still change during that window 😭

Picture a front-page newspaper photo with a one-hour freshness lifetime. No user sees a cached photo more than an hour old. But the photo could get updated at any moment, so different users might see different photos for up to an hour, depending on what's in their caches. Totally legal under the caching rules in [RFC7234], just a little chaotic πŸ™ˆ

When users need to be sure nothing changed, they usually hit the reload (or refresh) button. That sends a conditional request [RFC7232], and the server either returns a new representation or, if nothing changed, a 304 (Not Modified) response [RFC7232]. A user agent that understands HTML and fetches its sub-resources can fire off hundreds of conditional requests just to refresh one page [REQPERPAGE] πŸ’€

Some content providers avoid all that by never making more than one variant of a sub-resource. They use "versioned" URLs instead. When something needs an update, it gets published under a brand-new URL, usually with an identifier for that version baked into the path. Then every reference gets switched to the new path πŸ”

For example, https://www.example.com/101016/main.css might get updated and republished as https://www.example.com/102026/main.css, and any links pointing at it change at the same time.

This pattern means you can use a really big freshness lifetime for the sub-resource without guessing when it'll change next. Iconic πŸ‘‘

Unfortunately, the user agent has no idea when a site is using the versioned URL pattern. So user-driven refreshes still produce wasted conditional requests for every sub-resource, and each one just comes back as a 304 πŸ₯²

The immutable HTTP response Cache-Control extension fixes this. It lets servers flag responses that won't be updated during their freshness lifetimes ✨

Basically, it tells clients that any conditional request for that response can be skipped safely, with no worries about it having changed πŸ¦‹

1.1. Notational Conventions πŸ“

Here's the vocab: 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 interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here. Lowercase is just vibes πŸ’…

2. The Immutable Cache-Control Extension πŸ”

When it shows up in an HTTP response, the immutable Cache-Control extension tells you the origin server won't update that resource's representation during the response's freshness lifetime 🧚

Clients SHOULD NOT issue a conditional request during the response's freshness lifetime (e.g., upon a reload), unless the user explicitly overrides that (e.g., with a force reload) πŸ™…β€β™€οΈ

The immutable extension only applies during the freshness lifetime of the stored response. Stale responses SHOULD be revalidated the way they normally would be without the immutable extension ⏰

The immutable extension takes no arguments. If any arguments do show up, they have no meaning and MUST be ignored. Multiple instances of the extension count as just one. And if an immutable Cache-Control extension appears in a request, it does absolutely nothing 🫠

2.1. About Intermediaries πŸ§ƒ

An immutable response means the same thing to proxy clients as it does to user-agent-based clients. So proxies SHOULD skip conditionally revalidating fresh responses that have the immutable extension, unless the client sends a signal that validation is needed (e.g., a no-cache Cache-Control request directive, defined in Section 5.2.1.4 of [RFC7234]) πŸ“

A proxy that uses the immutable extension to skip a conditional revalidation can choose whether to answer its client with a 304 or a 200 response, based on the request headers it received πŸ’œ

2.2. Example πŸŽ€

Cache-Control: max-age=31536000, immutable

3. Security Considerations 🚨

Okay, serious moment, please pay attention 😀 The immutable mechanism acts as a form of soft pinning. And like every pinning mechanism, it creates a vector for amplifying cache corruption incidents, including cache-poisoning attacks. That's a big deal. Three mitigations are suggested for this risk:

  • Clients SHOULD ignore the immutable extension from resources that aren't part of an authenticated context, such as HTTPS. Authenticated resources are much less vulnerable to cache poisoning πŸ”’
  • User agents often offer two refresh mechanisms: reload, and some form of force-reload. The force-reload is what fixes interrupted loads and other corruption. These reloads, which are typically triggered by no-cache request attributes, SHOULD ignore the immutable extension as well πŸ› οΈ
  • Clients SHOULD ignore the immutable extension for resources that don't give a strong indication that the stored response size is the correct response size, such as responses delimited by connection close 🧯

4. IANA Considerations πŸ“‹

The immutable extension has been registered in the "Hypertext Transfer Protocol (HTTP) Cache Directive Registry", following the guidelines in Section 7.1 of [RFC7234] πŸ—ƒοΈ

  • Cache Directive: immutable
  • Reference: RFC 8246

5. References πŸ“š

5.1. Normative References

5.2. Informative References

Acknowledgments 🫢

Huge thanks to Ben Maurer for partnering on developing and testing this idea 🌟 Thanks to Amos Jeffries for help with proxy interactions, and to Mark Nottingham for help with the documentation πŸ’–

Author's Address πŸ’Œ

Patrick McManus Mozilla

Email: mcmanus@ducksong.com

πŸ“¦ where this page comes from