<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-ietf-httpbis-targeted-cache-control-04" number="9213" submissionType="IETF" category="std" consensus="true" tocInclude="true" sortRefs="true" symRefs="true" obsoletes="" updates="" xml:lang="en" version="3">
  <front>
    <title abbrev="Targeted HTTP Cache Control">Targeted HTTP Cache Control</title>
    <seriesInfo name="RFC" value="9213"/>
    <author initials="S." surname="Ludin" fullname="Stephen Ludin">
      <organization>Akamai</organization>
      <address>
        <email>sludin@ludin.org</email>
      </address>
    </author>
    <author initials="M." surname="Nottingham" fullname="Mark Nottingham">
      <organization>Fastly</organization>
      <address>
        <postal>
          <postalLine>Prahran</postalLine>
          <postalLine>Australia</postalLine>
        </postal>
        <email>mnot@mnot.net</email>
        <uri>https://www.mnot.net/</uri>
      </address>
    </author>
    <author initials="Y." surname="Wu" fullname="Yuchen Wu">
      <organization>Cloudflare</organization>
      <address>
        <email>me@yuchenwu.net</email>
      </address>
    </author>
    <date year="2022" month="June" />
    <area>Applications and Real-Time</area>
    <workgroup>HTTP</workgroup>
    <keyword>CDN</keyword>
    <keyword>Content Delivery Network</keyword>
    <keyword>Caching</keyword>
    <abstract>

<t>
This specification defines a convention for HTTP response header fields that allow cache directives to be targeted at specific caches or classes of caches. It also defines one such header field, the CDN-Cache-Control response header field, which is targeted at content delivery network (CDN) caches.

    </t>
    </abstract>
  </front>
  <middle>
    <section anchor="introduction" numbered="true" toc="default">
      <name>Introduction</name>
      <t>Modern deployments of HTTP often use multiple layers of caching. For example, a website might use a cache on the origin server itself; it might deploy a caching layer in the same network as the origin server, it might use one or more CDNs that are distributed throughout the Internet, and it might benefit from browser caching as well.</t>

      <t>Because it is often desirable to control these different classes of caches separately, some means of targeting cache directives at them is necessary. For example, if a publisher has a mechanism to invalidate the contents of a cache that it has a relationship with (such as a CDN cache), they might be more comfortable assigning a more generous caching policy to it while still wanting to restrict the behavior of other caches.</t>
      <t>The HTTP Cache-Control response header field (defined in <xref section="5.2" sectionFormat="of" target="HTTP-CACHING" format="default"/>) is widely used to direct caching behavior. However, it is relatively undifferentiated; while some cache directives (e.g., s-maxage) are targeted at a specific class of caches (for s-maxage, shared caches), targeting is not consistently available across all existing cache directives (e.g., stale-while-revalidate). This is problematic especially as the number of caching extensions grows along with the number of potential targets.</t>
      <t>Some implementations have defined ad hoc control mechanisms to overcome this issue, but their interoperability is low. <xref target="targeted" format="default"/> defines a standard framework for targeted cache control using HTTP response headers, and <xref target="cdn-cache-control" format="default"/> defines one such header: the CDN-Cache-Control response header field.</t>
      <section anchor="notational-conventions" numbered="true" toc="default">
        <name>Notational Conventions</name>
         <t>
    The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>",
    "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL
    NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>",
    "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
    "<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are
    to be interpreted as described in BCP&nbsp;14 <xref target="RFC2119"/>
    <xref target="RFC8174"/> when, and only when, they appear in all capitals,
    as shown here.
        </t>
      </section>
    </section>
    <section anchor="targeted" numbered="true" toc="default">
      <name>Targeted Cache-Control Header Fields</name>
      <t>A Targeted Cache-Control Header Field (hereafter "targeted field") is an HTTP response header field that has the same semantics as the Cache-Control response header field (<xref section="5.2" sectionFormat="comma" target="HTTP-CACHING" format="default"/>). However, it has a distinct field name that indicates the target for its cache directives.</t>
      <t>For example:</t>
      <sourcecode type="http-message"><![CDATA[
CDN-Cache-Control: max-age=60
]]></sourcecode>
      <t>is a targeted field that applies to CDNs, as defined in <xref target="cdn-cache-control" format="default"/>.</t>
      <section anchor="syntax" numbered="true" toc="default">
        <name>Syntax</name>
        <t>Targeted fields are Dictionary Structured Fields (<xref section="3.2" sectionFormat="of" target="RFC8941" format="default"/>). Each member of the Dictionary is an HTTP cache response directive (<xref section="5.2.2" sectionFormat="of" target="HTTP-CACHING" format="default"/>) including extension response directives (as per <xref section="5.2.3" sectionFormat="of" target="HTTP-CACHING" format="default"/>). Note that while targeted fields often have the same syntax as Cache-Control fields, differences in error handling mean that using a Cache-Control parser rather than a Structured Fields parser can introduce interoperability issues.</t>
        <t>Because cache directives are not defined in terms of structured data types, it is necessary to map their values into the appropriate types. <xref section="5.2" sectionFormat="of" target="HTTP-CACHING" format="default"/> defines cache directive values to be either absent, a quoted-string, or a token.</t>
        <t>This means that cache directives that have no value will be mapped to a Boolean (<xref section="3.3.6" sectionFormat="of" target="RFC8941" format="default"/>). When the value is a quoted-string, it will be mapped to a String (<xref section="3.3.3" sectionFormat="of" target="RFC8941" format="default"/>), and when it is a token, it will map to a Token (<xref section="3.3.4" sectionFormat="of" target="RFC8941" format="default"/>), an Integer (<xref section="3.3.1" sectionFormat="of" target="RFC8941" format="default"/>), or a Decimal (<xref section="3.3.2" sectionFormat="of" target="RFC8941" format="default"/>), depending on the content of the value.</t>
        <t>For example, the max-age directive (<xref section="5.2.2.1" sectionFormat="of" target="HTTP-CACHING" format="default"/>) has an integer value; no-store (<xref section="5.2.2.5" sectionFormat="of" target="HTTP-CACHING" format="default"/>) always has a Boolean true value, and no-cache (<xref section="5.2.2.4" sectionFormat="of" target="HTTP-CACHING" format="default"/>) has a value that can be either Boolean true or a string containing a comma-delimited list of field names.</t>
        <t>Implementations <bcp14>MUST NOT</bcp14> generate values that violate these inferred constraints on the cache directive's value. In particular, string values whose first character is not alphabetic or "*" <bcp14>MUST</bcp14> be generated as Strings so that they are not mistaken for other types.</t>
        <t>Implementations <bcp14>SHOULD NOT</bcp14> consume values that violate these inferred constraints. For example, a consuming implementation that coerces a max-age with a decimal value into an integer would behave differently than other implementations, potentially causing interoperability issues.</t>
        <t>Parameters received on cache directives are to be ignored, unless other handling is explicitly specified.</t>

	<t>If a targeted field in a given response is empty, or a parsing error is encountered, that field <bcp14>MUST</bcp14> be ignored by the cache (i.e., it behaves as if the field were not present, likely falling back to other cache-control mechanisms present).</t>

	
      </section>
      <section anchor="cache-behavior" numbered="true" toc="default">
        <name>Cache Behavior</name>

	<t>A cache that implements this specification maintains a target list. A target list is an ordered list of the targeted field names that it uses for caching policy, with the order reflecting priority from most applicable to least. The target list might be fixed, user configurable, or generated per request, depending upon the implementation.</t>
        <t>For example, a CDN cache might support both CDN-Cache-Control and a header specific to that CDN, ExampleCDN-Cache-Control, with the latter overriding the former. Its target list would be:</t>

	<artwork  align="left" ><![CDATA[
  [ExampleCDN-Cache-Control, CDN-Cache-Control]
  ]]></artwork>
        <t>When a cache that implements this specification receives a response with one or more of the header field names on its target list, the cache <bcp14>MUST</bcp14> select the first (in target-list order) field with a valid, non-empty value and use its value to determine the caching policy for the response, and it <bcp14>MUST</bcp14> ignore the Cache-Control and Expires header fields in that response, unless no valid, non-empty value is available from the listed header fields.</t>
        <t>Note that this occurs on a response-by-response basis; if no member of the cache's target list is present, valid, and non-empty, a cache falls back to other cache control mechanisms as required by HTTP <xref target="HTTP-CACHING" format="default"/>.</t>
        <t>Targeted fields that are not on a cache's target list <bcp14>MUST NOT</bcp14> change that cache's behavior and <bcp14>MUST</bcp14> be passed through.</t>
        <t>Caches that use a targeted field <bcp14>MUST</bcp14> implement the semantics of the following cache directives:</t>
        <ul spacing="normal">
          <li>max-age</li>
          <li>must-revalidate</li>
          <li>no-store</li>
          <li>no-cache</li>
          <li>private</li>
        </ul>
        <t>Furthermore, they <bcp14>SHOULD</bcp14> implement other cache directives (including extension cache directives) that they support in the Cache-Control response header field.</t>
        <t>The semantics and precedence of cache directives in a targeted field are the same as those in Cache-Control. In particular, no-store and no-cache make max-age inoperative, and unrecognized extension directives are ignored.</t>
      </section>
      <section anchor="interaction-with-http-freshness" numbered="true" toc="default">
        <name>Interaction with HTTP Freshness</name>
        <t>HTTP caching has a single, end-to-end freshness model defined in <xref section="4.2" sectionFormat="of" target="HTTP-CACHING" format="default"/>. When additional freshness mechanisms are only available to some caches along a request path (for example, using targeted fields), their interactions need to be carefully considered. In particular, a targeted cache might have longer freshness lifetimes available to it than other caches, causing it to serve responses that appear to be prematurely (or even immediately) stale to those other caches, negatively impacting cache efficiency.</t>
        <t>For example, a response stored by a CDN cache might be served with the following headers:</t>
        <sourcecode type="http-message"><![CDATA[
Age: 1800
Cache-Control: max-age=600
CDN-Cache-Control: max-age=3600
]]></sourcecode>
        <t>From the CDN's perspective, this response is still fresh after being cached for 30 minutes, while from the standpoint of other caches, this response is already stale. See <xref target="AGE-PENALTY" format="default"/> for more discussion.</t>
        <t>When the targeted cache has a strong coherence mechanism (e.g., the origin server has the ability to proactively invalidate cached responses), it is often desirable to mitigate these effects. Some techniques seen in deployments include:</t>
        <ul spacing="normal">
          <li>Removing the Age header field</li>
          <li>Updating the Date header field value to the current time</li>
          <li>Updating the Expires header field value to the current time, plus any Cache-Control: max-age value</li>
        </ul>
        <t>This specification does not place any specific requirements on implementations to mitigate these effects, but definitions of targeted fields can do so.</t>
      </section>
      <section anchor="defining-targeted-fields" numbered="true" toc="default">
        <name>Defining Targeted Fields</name>
        <t>A targeted field for a particular class of cache can be defined by requesting registration in the "Hypertext Transfer Protocol (HTTP) Field Name Registry" (<eref target="https://www.iana.org/assignments/http-fields/" brackets="angle"/>).</t>
        <t>Registration requests can use this document as the specification document; in which case, the Comments field should clearly define the class of caches that the targeted field applies to. Alternatively, if other documentation for the field has been created, it can be used as the specification document.</t>
        <t>By convention, targeted fields have the suffix "-Cache-Control", e.g., "ExampleCDN-Cache-Control". However, this suffix <bcp14>MUST NOT</bcp14> be used on its own to identify targeted fields; it is only a convention.</t>
      </section>
    </section>
    <section anchor="cdn-cache-control" numbered="true" toc="default">
      <name>The CDN-Cache-Control Targeted Field</name>
      <t>The CDN-Cache-Control response header field is a targeted field (<xref target="targeted" format="default"/>) that allows origin servers to control the behavior of CDN caches interposed between them and clients separately from other caches that might handle the response.</t>
      <t>It applies to caches that are part of a distributed network that operate on behalf of an origin server (commonly called a CDN).</t>
      <t>CDN caches that use CDN-Cache-Control will typically forward this header so that downstream CDN caches can use it as well. However, they <bcp14>MAY</bcp14> remove it when this is undesirable (for example, when configured to do so because it is known not to be used downstream).</t>
      <section anchor="examples" numbered="true" toc="default">
        <name>Examples</name>
        <t>For example, the following header fields would instruct a CDN cache (i.e., a cache with a target list of <tt>[CDN-Cache-Control]</tt>) to consider the response fresh for 600 seconds, other shared caches to consider the response fresh for 120 seconds, and any remaining caches to consider the response fresh for 60 seconds:</t>
        <sourcecode type="http-message"><![CDATA[
Cache-Control: max-age=60, s-maxage=120
CDN-Cache-Control: max-age=600
]]></sourcecode>
        <t>These header fields would instruct a CDN cache to consider the response fresh for 600 seconds, while all other caches would be prevented from storing it:</t>
        <sourcecode type="http-message"><![CDATA[
CDN-Cache-Control: max-age=600
Cache-Control: no-store
]]></sourcecode>
        <t>Because CDN-Cache-Control is not present, this header field would prevent all caches from storing the response:</t>
        <sourcecode type="http-message"><![CDATA[
Cache-Control: no-store
]]></sourcecode>
        <t>Whereas these would prevent all caches except for CDN caches from storing the response:</t>
        <sourcecode type="http-message"><![CDATA[
Cache-Control: no-store
CDN-Cache-Control: none
]]></sourcecode>
        <t>(Note that 'none' is not a registered cache directive; it is here to avoid sending a header field with an empty value, which would be ignored.)</t>
      </section>
    </section>
    <section anchor="iana-considerations" numbered="true" toc="default">
      <name>IANA Considerations</name>
      <t>IANA has registered the following entry in the "Hypertext Transfer Protocol (HTTP) Field Name Registry" defined by <xref target="HTTP" format="default"/>:</t>
      <dl spacing="compact">
        <dt>Field Name:</dt>
        <dd>CDN-Cache-Control</dd>
        <dt>Status:</dt>
        <dd>permanent</dd>
        <dt>Specification Document:</dt>
        <dd>RFC 9213</dd>
        <dt>Comments:</dt>

        <dd>Cache directives targeted at content delivery networks</dd>
       </dl>
    </section>
    <section anchor="security-considerations" numbered="true" toc="default">
      <name>Security Considerations</name>
      <t>The security considerations of HTTP caching <xref target="HTTP-CACHING" format="default"/> apply.</t>
      <t>The ability to carry multiple caching policies on a response can result in confusion about how a response will be cached in different systems, potentially resulting in unintentional reuse of responses with sensitive information. For this reason, care must be exercised.</t>
    </section>
  </middle>
  <back>

    <displayreference target="RFC8941" to="STRUCTURED-FIELDS"/>
    <references>


      <name>References</name>
      <references>
        <name>Normative References</name>

<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml"/>

<reference anchor='HTTP' target="https://www.rfc-editor.org/info/rfc9110">
<front>
<title>HTTP Semantics</title>
<author initials='R' surname='Fielding' fullname='Roy Fielding' role="editor">
<organization />
</author>
<author initials='M' surname='Nottingham' fullname='Mark Nottingham' role="editor">
<organization />
</author>
<author initials='J' surname='Reschke' fullname='Julian Reschke' role="editor">
<organization />
</author>
<date year='2022' month='June' />
</front>
 <seriesInfo name='STD' value='97'/>
 <seriesInfo name='RFC' value='9110'/>
  <seriesInfo name='DOI' value='10.17487/RFC9110'/>
</reference>



<reference anchor='HTTP-CACHING' target="https://www.rfc-editor.org/info/rfc9111">
<front>
<title>HTTP Caching</title>
<author initials='R' surname='Fielding' fullname='Roy T. Fielding' role="editor">
<organization />
</author>
<author initials='M' surname='Nottingham' fullname='Mark Nottingham' role="editor">
<organization />
</author>
<author initials='J' surname='Reschke' fullname='Julian Reschke' role="editor">
<organization />
</author>
<date year='2022' month='June' />
</front>
 <seriesInfo name='STD' value='98'/>
 <seriesInfo name='RFC' value='9111'/>
  <seriesInfo name='DOI' value='10.17487/RFC9111'/>
</reference>



<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8941.xml"/>
<xi:include href="https://xml2rfc.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml"/>


</references>
      <references>
        <name>Informative References</name>

        <reference anchor="AGE-PENALTY" target="https://dl.acm.org/doi/10.5555/1251440.1251447">
          <front>
            <title>The age penalty and its effect on cache performance</title>
            <author initials="E." surname="Cohen" fullname="Edith Cohen">
              <organization>AT&amp;T Labs - Research</organization>
            </author>
            <author initials="H." surname="Kaplan" fullname="Haim Kaplan">
              <organization>School of Computer Science, Tel-Aviv University</organization>
            </author>
            <date year="2001" month="March"/>
          </front>
        </reference>
      </references>
    </references>

  </back>
</rfc>
