<?xml version="1.0" encoding="UTF-8"?>
<!--
    This XML document is the output of clean-for-DTD.xslt; a tool that strips
    extensions to RFC2629(bis) from documents for processing with xml2rfc.
-->
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?><!-- generated by https://github.com/cabo/kramdown-rfc2629 version 1.0.29 -->
<?rfc toc="yes"?>
<?rfc tocindent="yes"?>
<?rfc sortrefs="yes"?>
<?rfc symrefs="yes"?>
<?rfc strict="yes"?>
<?rfc compact="yes"?>
<?rfc subcompact="yes"?>
<?rfc comments="yes"?>
<?rfc inline="yes"?>
<!DOCTYPE rfc
  SYSTEM "rfc2629.dtd">
<rfc ipr="trust200902" docName="draft-ietf-httpbis-key-01" category="std" obsoletes="" updates="" submissionType="IETF"><front><title abbrev="Key">The Key HTTP Response Header Field</title><author initials="R." surname="Fielding" fullname="Roy T. Fielding"><organization>Adobe Systems Incorporated</organization><address><email>fielding@gbiv.com</email><uri>http://roy.gbiv.com/</uri></address></author><author initials="M." surname="Nottingham" fullname="Mark Nottingham"><organization/><address><email>mnot@mnot.net</email><uri>https://www.mnot.net/</uri></address></author><date year="2016"/><area>Applications and Real-Time</area><workgroup>HTTP Working Group</workgroup><keyword>content negotiation</keyword><abstract><t>The ‘Key’ header field for HTTP responses allows an origin server to describe the secondary cache
key (RFC 7234, Section 4.1) for a resource, by conveying what is effectively a short algorithm
that can be used upon later requests to determine if a stored response is reusable for a given
request.</t><t>Key has the advantage of avoiding an additional round trip for validation whenever a new request
differs slightly, but not significantly, from prior requests.</t><t>Key also informs user agents of the request characteristics that might result in different content,
which can be useful if the user agent is not sending request header fields in order to reduce the
risk of fingerprinting.</t></abstract><note title="Note to Readers"><t>Discussion of this draft takes place on the HTTP working group mailing list 
(ietf-http-wg@w3.org), which is archived at <eref target="https://lists.w3.org/Archives/Public/ietf-http-wg/">https://lists.w3.org/Archives/Public/ietf-http-wg/</eref>.</t><t>Working Group information can be found at <eref target="http://httpwg.github.io/">http://httpwg.github.io/</eref>; source 
code and issues list for this draft can be found at <eref target="https://github.com/httpwg/http-extensions/labels/key">https://github.com/httpwg/http-extensions/labels/key</eref>.</t></note></front><middle><section anchor="introduction" toc="default" title="Introduction"><t>In HTTP caching <xref target="RFC7234" format="default"/>, the Vary response header field effectively modifies the key used to
store and access a response to include information from the request’s headers. This “secondary
cache key” allows proactive content negotiation <xref target="RFC7231" format="default"/> to work with caches.</t><t>Vary’s operation is generic; it works well when caches understand the semantics of the selecting
headers. For example, the Accept-Language request header field has a well-defined syntax for
expressing the client’s preferences; a cache that understands this header field can select the
appropriate response (based upon its Content-Language header field) and serve it to a client,
without any knowledge of the underlying resource.</t><t>Vary does not work as well when the criteria for selecting a response are specific to the resource.
For example, if the nature of the response depends upon the presence or absence of a particular
Cookie (<xref target="RFC6265" format="default"/>) in a request, Vary doesn’t have a mechanism to offer enough fine-grained,
resource-specific information to aid a cache’s selection of the appropriate response.</t><t>This document defines a new response header field, “Key”, that allows resources to describe the
secondary cache key in a fine-grained, resource-specific manner, leading to improved cache
efficiency when responses depend upon such headers.</t><section anchor="examples" toc="default" title="Examples"><t>For example, this response header field:</t><figure title="" suppress-title="false" align="left" alt="" width="" height=""><artwork type="example" xml:space="preserve" name="" align="left" alt="" width="" height=""><![CDATA[

  Key: cookie;param=_sess;param=ID
]]></artwork></figure><t>indicates that the selected response depends upon the “_sess” and “ID” cookie values.</t><t>This Key:</t><figure title="" suppress-title="false" align="left" alt="" width="" height=""><artwork type="example" xml:space="preserve" name="" align="left" alt="" width="" height=""><![CDATA[

  Key: user-agent;substr=MSIE
]]></artwork></figure><t>indicates that there are two possible secondary cache keys for this resource; one for requests
whose User-Agent header field contains “MSIE”, and another for those that don’t.</t><t>A more complex example:</t><figure title="" suppress-title="false" align="left" alt="" width="" height=""><artwork type="example" xml:space="preserve" name="" align="left" alt="" width="" height=""><![CDATA[

  Key: user-agent;substr=MSIE;Substr="mobile", Cookie;param="ID"
]]></artwork></figure><t>indicates that the selected response depends on the presence of two strings in the User-Agent
request header field, as well as the value of the “ID” cookie request header field.</t></section><section anchor="notational-conventions" toc="default" title="Notational Conventions"><t>The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”,
“RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in
<xref target="RFC2119" format="default"/>.</t><t>This document uses the Augmented Backus-Naur Form (ABNF) notation of <xref target="RFC5234" format="default"/> (including the
DQUOTE rule), and the list rule extension defined in <xref target="RFC7230" format="default"/>, Section 7. It includes by
reference the field-name, quoted-string and quoted-pair rules from that document, the OWS rule from 
<xref target="RFC7230" format="default"/> and the parameter rule from <xref target="RFC7231" format="default"/>.</t></section></section><section anchor="the-key-response-header-field" toc="default" title="The “Key” Response Header Field"><t>The “Key” response header field describes the portions of the request that the resource currently
uses to select representations.</t><t>As such, its semantics are similar to the “Vary” response header field, but it allows more
fine-grained description, using “key parameters”.</t><t>Caches can use this information as part of determining whether a stored response can be used to
satisfy a given request. When a cache knows and fully understands the Key header field for a given
resource, it MAY ignore the Vary response header field in any stored responses for it.</t><t>Additionally, user agents can use Key to discover if additional request header fields might
influence the resource’s selection of responses.</t><t>The Key field-value is a comma-delimited list of selecting header fields (similar to Vary), with
zero to many parameters each, delimited by semicolons.</t><figure title="" suppress-title="false" align="left" alt="" width="" height=""><artwork type="abnf7230" xml:space="preserve" name="" align="left" alt="" width="" height=""><![CDATA[

  Key       = 1#key-value
  key-value = field-name *( OWS ";" OWS parameter )
]]></artwork></figure><t>Note that, as per <xref target="RFC7231" format="default"/>, parameter names are case-insensitive, and parameter values can be
double-quoted strings (potentially with “\“-escaped characters inside).</t><t>The following header fields have the same effect:</t><figure title="" suppress-title="false" align="left" alt="" width="" height=""><artwork type="example" xml:space="preserve" name="" align="left" alt="" width="" height=""><![CDATA[

  Vary: Accept-Encoding, Cookie
  Key: Accept-Encoding, Cookie
]]></artwork></figure><t>However, Key’s use of parameters allows:</t><figure title="" suppress-title="false" align="left" alt="" width="" height=""><artwork type="example" xml:space="preserve" name="" align="left" alt="" width="" height=""><![CDATA[

  Key: Accept-Encoding, Cookie; param=foo
]]></artwork></figure><t>to indicate that the secondary cache key depends upon the Accept-Encoding header field and the
“foo” Cookie.</t><t>One important difference between Vary and Key is how they are applied. Vary is specified to be
specific to the response it occurs within, whereas Key is specific to the resource (as identified
by the request URL) it is associated with. The most recent key you receive for a given resource is
applicable to all responses from that resource.</t><t>This difference allows more efficient implementation (and reflects practices that many caches use
in implementing Vary already).</t><t>This specification defines a selection of Key parameters to address common use cases such as
selection upon individual Cookie header fields, User-Agent substrings and numerical ranges. Future
parameters may define further capabilities.</t><section anchor="relationship-with-vary" toc="default" title="Relationship with Vary"><t>Origin servers SHOULD still send Vary when using Key, to ensure backwards compatibility.</t><t>For example,</t><figure title="" suppress-title="false" align="left" alt="" width="" height=""><artwork type="example" xml:space="preserve" name="" align="left" alt="" width="" height=""><![CDATA[

  Vary: User-Agent
  Key: User-Agent;substr="mozilla"
]]></artwork></figure><t>Note that, in some cases, it may be better to explicitly use “Vary: *” if clients and caches don’t have any practical way to use the Vary header field’s value. For example,</t><figure title="" suppress-title="false" align="left" alt="" width="" height=""><artwork type="example" xml:space="preserve" name="" align="left" alt="" width="" height=""><![CDATA[

  Vary: *
  Key: Cookie;param="ID"
]]></artwork></figure><t>Except when Vary: * is used, the set of headers used in Key SHOULD reflect the same request header fields as Vary does, even if they don’t have parameters. For example,</t><figure title="" suppress-title="false" align="left" alt="" width="" height=""><artwork type="example" xml:space="preserve" name="" align="left" alt="" width="" height=""><![CDATA[

  Vary: Accept-Encoding, User-Agent
  Key: Accept-Encoding, User-Agent;substr="mozilla"
]]></artwork></figure><t>Here, Accept-Encoding is included in Key without parameters; caches MAY treat these as they do
values in the Vary header, relying upon knowledge of their generic semantics to select an
appropriate response.</t></section><section anchor="calculating-a-secondary-cache-key" toc="default" title="Calculating a Secondary Cache Key"><t>When used by a cache to determine whether a stored response can be used to satisfy a presented
request, each field-name in Key identifies a potential request header, just as with the Vary
response header field.</t><t>However, each of these can have zero to many key parameters that change how the response selection
process (as defined in <xref target="RFC7234" format="default"/>, Section 4.3)) works.</t><t>In particular, when a cache fully implements this specification, it creates a secondary cache key
for every request by following the instructions in the Key header field, ignoring the Vary header
for this purpose.</t><t>Then, when a new request is presented, the secondary cache key generated for that request can be
compared to the stored one to find the appropriate response, to determine if it can be selected.</t><t>To generate a secondary cache key for a given request (including that which is stored with a
response) using Key, the following steps are taken:</t><t><list style="format %d)" counter="a"><t>If the Key header field is not present on the most recent cacheable (as per <xref target="RFC7234" format="default"/>, Section 3)) response seen for the resource, abort this algorithm (i.e., fall back to using Vary to determine the secondary cache key).</t><t>Let <spanx style="verb" xml:space="preserve">key_value</spanx> be the result of Creating a Header Field Value (<xref target="value" format="default"/>) with <spanx style="verb" xml:space="preserve">key</spanx> as the <spanx style="verb" xml:space="preserve">target_field_name</spanx> and the most recently seen response header list for the resource as <spanx style="verb" xml:space="preserve">header_list</spanx>.</t><t>Let <spanx style="verb" xml:space="preserve">secondary_key</spanx> be an empty string.</t><t>Create <spanx style="verb" xml:space="preserve">key_list</spanx> by splitting <spanx style="verb" xml:space="preserve">key_value</spanx> on “,” characters, excepting “,” characters within quoted strings, as per <xref target="RFC7230" format="default"/> Section 3.2.6..</t><t>For <spanx style="verb" xml:space="preserve">key_item</spanx> in <spanx style="verb" xml:space="preserve">key_list</spanx>:  <list style="format %d)" counter="b"><t>Remove any leading and trailing WSP from <spanx style="verb" xml:space="preserve">key_item</spanx>.</t><t>If <spanx style="verb" xml:space="preserve">key_item</spanx> does not contain a “;” character, fail parameter processing (<xref target="fail-param" format="default"/>) and skip to the next <spanx style="verb" xml:space="preserve">key_item</spanx>.</t><t>Let <spanx style="verb" xml:space="preserve">field_name</spanx> be the string before the first “;” character in <spanx style="verb" xml:space="preserve">key_item</spanx>, removing any WSP between them.</t><t>Let <spanx style="verb" xml:space="preserve">field_value</spanx> be the result of Creating a Header Field Value (<xref target="value" format="default"/>) with <spanx style="verb" xml:space="preserve">field_name</spanx> as the <spanx style="verb" xml:space="preserve">target_field_name</spanx> and the request header list as <spanx style="verb" xml:space="preserve">header_list</spanx>.</t><t>Let <spanx style="verb" xml:space="preserve">parameters</spanx> be the string after the first “;” character in <spanx style="verb" xml:space="preserve">key_item</spanx>, removing any WSP between them.</t><t>Create <spanx style="verb" xml:space="preserve">param_list</spanx> by splitting <spanx style="verb" xml:space="preserve">parameters</spanx> on “;” characters, excepting “;” characters within quoted strings, as per <xref target="RFC7230" format="default"/> Section 3.2.6.</t><t>For <spanx style="verb" xml:space="preserve">parameter</spanx> in <spanx style="verb" xml:space="preserve">param_list</spanx>:      <list style="format %d)" counter="c"><t>If <spanx style="verb" xml:space="preserve">parameter</spanx> does not contain a “=”, fail parameter processing (<xref target="fail-param" format="default"/>) and skip to the next <spanx style="verb" xml:space="preserve">key_item</spanx>.</t><t>Remove any WSP at the beginning and/or end of <spanx style="verb" xml:space="preserve">parameter</spanx>.</t><t>Let <spanx style="verb" xml:space="preserve">param_name</spanx> be the string before the first “=” character in <spanx style="verb" xml:space="preserve">parameter</spanx>, case-normalized to lowercase.</t><t>If <spanx style="verb" xml:space="preserve">param_name</spanx> does not identify a Key parameter processing algorithm that is implemented, fail parameter processing (<xref target="fail-param" format="default"/>) and skip to the next <spanx style="verb" xml:space="preserve">key_item</spanx>.</t><t>Let <spanx style="verb" xml:space="preserve">param_value</spanx> be the string after the first “=” character in <spanx style="verb" xml:space="preserve">parameter</spanx>.</t><t>If the first and last characters of <spanx style="verb" xml:space="preserve">param_value</spanx> are both DQUOTE:          <list style="format %d)" counter="d"><t>Remove the first and last characters of <spanx style="verb" xml:space="preserve">param_value</spanx>.</t><t>Replace quoted-pairs within <spanx style="verb" xml:space="preserve">param_value</spanx> with the octet following the backslash, as per <xref target="RFC7230" format="default"/> Section 3.2.6.</t></list></t><t>If <spanx style="verb" xml:space="preserve">param_value</spanx> does not conform to the syntax defined for it by the parameter definition, fail parameter processing <xref target="fail-param" format="default"/> and skip to the next <spanx style="verb" xml:space="preserve">key_item</spanx>.</t><t>Run the identified processing algorithm on <spanx style="verb" xml:space="preserve">field_value</spanx> with the <spanx style="verb" xml:space="preserve">param_value</spanx>, and append the result to <spanx style="verb" xml:space="preserve">secondary_key</spanx>. If parameter processing fails <xref target="fail-param" format="default"/>, skip to the next <spanx style="verb" xml:space="preserve">key_item</spanx>.</t><t>Append a separator character (e.g., NULL) to <spanx style="verb" xml:space="preserve">secondary_key</spanx>.</t></list></t></list></t><t>Return <spanx style="verb" xml:space="preserve">secondary_key</spanx>.</t></list></t><t>Note that this specification does not require that exact algorithm to be implemented. However,
implementations’ observable behavior MUST be identical to running it. This includes parameter
processing algorithms; implementations MAY use different internal artefacts for secondary cache
keys, as long as the results are the same.</t><t>Likewise, while the secondary cache key associated with both stored and presented requests is
required to use the most recently seen Key header field for the resource in question, this can be
achieved using a variety of implementation strategies, including (but not limited to):</t><t><list style="symbols"><t>Generating a new secondary cache key for every stored response associated with the resource upon each request.</t><t>Caching the secondary cache key with the stored request/response pair and re-generating it when the Key header field is observed to change.</t><t>Caching the secondary cache key with the stored response and invalidating the stored response(s) when the Key header field is observed to change.</t></list></t><section anchor="value" toc="default" title="Creating a Header Field Value"><t>Given a header field name <spanx style="verb" xml:space="preserve">target_field_name</spanx> and <spanx style="verb" xml:space="preserve">header_list</spanx>, a list of (<spanx style="verb" xml:space="preserve">field_name</spanx>,
<spanx style="verb" xml:space="preserve">field_value</spanx>) tuples:</t><t><list style="format %d)" counter="e"><t>Let <spanx style="verb" xml:space="preserve">target_field_values</spanx> be an empty list.</t><t>For each (<spanx style="verb" xml:space="preserve">field_name</spanx>, <spanx style="verb" xml:space="preserve">field_value</spanx>) tuple in <spanx style="verb" xml:space="preserve">header_list</spanx>:  <list style="format %d)" counter="f"><t>If <spanx style="verb" xml:space="preserve">field_name</spanx> does not match <spanx style="verb" xml:space="preserve">target_field_name</spanx>, skip to the next tuple.</t><t>Strip leading and trailing WSP from <spanx style="verb" xml:space="preserve">field_value</spanx> and append it to <spanx style="verb" xml:space="preserve">target_field_values</spanx>.</t></list></t><t>If <spanx style="verb" xml:space="preserve">target_field_values</spanx> is empty, return an empty string.</t><t>Return the concatenation of <spanx style="verb" xml:space="preserve">target_field_values</spanx>, separating each with “,” characters.</t></list></t></section><section anchor="fail-param" toc="default" title="Failing Parameter Processing"><t>In some cases, a key parameter cannot determine a secondary cache key corresponding to its
nominated header field value. When this happens, Key processing needs to fail safely, so that the
correct behavior is observed.</t><t>When this happens, implementations MUST either behave as if the Key header was not present, or
assure that the nominated header fields being compared match, as per <xref target="RFC7234" format="default"/>, Section 4.1.</t></section></section><section anchor="key-parameters" toc="default" title="Key Parameters"><t>A Key parameter associates a name with a specific processing algorithm that takes two inputs; a
HTTP header value “header_value” (as described in <xref target="value" format="default"/>), and “parameter_value”, a string that
indicates how the identified header should be processed.</t><t>The set of key parameters (and their associated processing algorithms) is extensible; see <xref target="iana" format="default"/>.
This document defines the following key parameters:</t><section anchor="div" toc="default" title="div"><t>The “div” parameter normalizes positive integer header values into groups by dividing them by a
configured value.</t><t>Its value’s syntax is:</t><figure title="" suppress-title="false" align="left" alt="" width="" height=""><artwork type="abnf7230" xml:space="preserve" name="" align="left" alt="" width="" height=""><![CDATA[

div    = 1*DIGIT
]]></artwork></figure><t>To process a set of header fields against a div parameter, follow these steps (or their equivalent):</t><t><list style="format %d)"><t>If <spanx style="verb" xml:space="preserve">parameter_value</spanx> is “0”, fail parameter processing <xref target="fail-param" format="default"/>.</t><t>If <spanx style="verb" xml:space="preserve">header_value</spanx> is the empty string, return “none”.</t><t>If <spanx style="verb" xml:space="preserve">header_value</spanx> contains a “,”, remove it and all subsequent characters.</t><t>Remove all WSP characters from <spanx style="verb" xml:space="preserve">header_value</spanx>.</t><t>If <spanx style="verb" xml:space="preserve">header_value</spanx> does not match the div ABNF rule, fail parameter processing (<xref target="fail-param" format="default"/>).</t><t>Return the quotient of <spanx style="verb" xml:space="preserve">header_value</spanx> / <spanx style="verb" xml:space="preserve">parameter_value</spanx> (omitting the modulus).</t></list></t><t>For example, the Key:</t><figure title="" suppress-title="false" align="left" alt="" width="" height=""><artwork type="example" xml:space="preserve" name="" align="left" alt="" width="" height=""><![CDATA[

Key: Bar;div=5
]]></artwork></figure><t>indicates that the “Bar” header’s field value should be partitioned into groups of 5. Thus, the
following field values would be considered the same (because, divided by 5, they all result in 0):</t><figure title="" suppress-title="false" align="left" alt="" width="" height=""><artwork type="example" xml:space="preserve" name="" align="left" alt="" width="" height=""><![CDATA[

Bar: 1
Bar: 3 , 42
Bar: 4, 1
]]></artwork></figure><t>whereas these would be considered to be in a different group (because, divided by 5, they all result in 2);</t><figure title="" suppress-title="false" align="left" alt="" width="" height=""><artwork type="example" xml:space="preserve" name="" align="left" alt="" width="" height=""><![CDATA[

Bar: 12
Bar: 10
Bar: 14, 1
]]></artwork></figure></section><section anchor="partition" toc="default" title="partition"><t>The “partition” parameter normalizes positive numeric header values into pre-defined segments.</t><t>Its value’s syntax is:</t><figure title="" suppress-title="false" align="left" alt="" width="" height=""><artwork type="abnf7230" xml:space="preserve" name="" align="left" alt="" width="" height=""><![CDATA[

partition = [ segment ] *( ":" [ segment ] )
segment   = [ 0*DIGIT "." ] 1*DIGIT
]]></artwork></figure><t>To process a set of header fields against a partition parameter, follow these steps (or their
equivalent):</t><t><list style="format %d)" counter="g"><t>If <spanx style="verb" xml:space="preserve">header_value</spanx> is the empty string, return “none”.</t><t>If <spanx style="verb" xml:space="preserve">header_value</spanx> contains a “,”, remove it and all subsequent characters.</t><t>Remove all WSP characters from <spanx style="verb" xml:space="preserve">header_value</spanx>.</t><t>If <spanx style="verb" xml:space="preserve">header_value</spanx> does not match the segment ABNF rule, fail parameter processing (<xref target="fail-param" format="default"/>).</t><t>Let <spanx style="verb" xml:space="preserve">segment_id</spanx> be 0.</t><t>Create a list <spanx style="verb" xml:space="preserve">segment_list</spanx> by splitting <spanx style="verb" xml:space="preserve">parameter_value</spanx> on “:” characters.</t><t>For each <spanx style="verb" xml:space="preserve">segment_value</spanx> in <spanx style="verb" xml:space="preserve">segment_list</spanx>:  <list style="format %d)" counter="h"><t>If <spanx style="verb" xml:space="preserve">header_value</spanx> is less than <spanx style="verb" xml:space="preserve">segment_value</spanx> when they are numerically compared, skip to step 7.</t><t>Increment <spanx style="verb" xml:space="preserve">segment_id</spanx> by 1.</t></list></t><t>Return <spanx style="verb" xml:space="preserve">segment_id</spanx>.</t></list></t><t>For example, the Key:</t><figure title="" suppress-title="false" align="left" alt="" width="" height=""><artwork type="example" xml:space="preserve" name="" align="left" alt="" width="" height=""><![CDATA[

Key: Foo;partition=20:30:40
]]></artwork></figure><t>indicates that the “Foo” header’s field value should be divided into four segments:</t><t><list style="symbols"><t>less than 20</t><t>20 to less than 30</t><t>30 to less than 40</t><t>forty or greater</t></list></t><t>Thus, the following headers would all be normalized to the first segment:</t><figure title="" suppress-title="false" align="left" alt="" width="" height=""><artwork type="example" xml:space="preserve" name="" align="left" alt="" width="" height=""><![CDATA[

Foo: 1
Foo: 0
Foo: 4, 54
Foo: 19.9
]]></artwork></figure><t>whereas the following would fall into the second segment:</t><figure title="" suppress-title="false" align="left" alt="" width="" height=""><artwork type="example" xml:space="preserve" name="" align="left" alt="" width="" height=""><![CDATA[

Foo: 20
Foo: 29.999
Foo:  24   , 10
]]></artwork></figure></section><section anchor="match" toc="default" title="match"><t>The “match” parameter is used to determine if an exact value occurs in a list of header values. It
is case-sensitive.</t><t>Its value’s syntax is:</t><figure title="" suppress-title="false" align="left" alt="" width="" height=""><artwork type="abnf7230" xml:space="preserve" name="" align="left" alt="" width="" height=""><![CDATA[

match  = ( token / quoted-string )
]]></artwork></figure><t>To process a set of header fields against a match parameter, follow these steps (or their
equivalent):</t><t><list style="format %d)" counter="i"><t>If <spanx style="verb" xml:space="preserve">header_value</spanx> is the empty string, return “none”.</t><t>Create <spanx style="verb" xml:space="preserve">header_list</spanx> by splitting <spanx style="verb" xml:space="preserve">header_value</spanx> on “,” characters.</t><t>For each <spanx style="verb" xml:space="preserve">header_item</spanx> in <spanx style="verb" xml:space="preserve">header_list</spanx>:  <list style="format %d)" counter="j"><t>Remove leading and trailing WSP characters in <spanx style="verb" xml:space="preserve">header_item</spanx>.</t><t>If the value of <spanx style="verb" xml:space="preserve">header_item</spanx> is character-for-character identical to <spanx style="verb" xml:space="preserve">parameter_value</spanx>, return “1”.</t></list></t><t>Return “0”.</t></list></t><t>For example, the Key:</t><figure title="" suppress-title="false" align="left" alt="" width="" height=""><artwork type="example" xml:space="preserve" name="" align="left" alt="" width="" height=""><![CDATA[

Key: Baz;match="charlie"
]]></artwork></figure><t>Would return “1” for the following header field values:</t><figure title="" suppress-title="false" align="left" alt="" width="" height=""><artwork type="example" xml:space="preserve" name="" align="left" alt="" width="" height=""><![CDATA[

Baz: charlie
Baz: foo, charlie
Baz: bar, charlie     , abc
]]></artwork></figure><t>and “0” for these:</t><figure title="" suppress-title="false" align="left" alt="" width="" height=""><artwork type="example" xml:space="preserve" name="" align="left" alt="" width="" height=""><![CDATA[

Baz: theodore
Baz: joe, sam
Baz: "charlie"
Baz: Charlie
Baz: cha rlie
Baz: charlie2
]]></artwork></figure></section><section anchor="substr" toc="default" title="substr"><t>The “substr” parameter is used to determine if a value occurs as a substring of an item in a list
of header values. It is case-sensitive.</t><t>Its value’s syntax is:</t><figure title="" suppress-title="false" align="left" alt="" width="" height=""><artwork type="abnf7230" xml:space="preserve" name="" align="left" alt="" width="" height=""><![CDATA[

substr  = ( token / quoted-string )
]]></artwork></figure><t>To process a set of header fields against a substr parameter, follow these steps (or their
equivalent):</t><t><list style="format %d)" counter="k"><t>If <spanx style="verb" xml:space="preserve">header_value</spanx> is the empty string, return “none”.</t><t>Create <spanx style="verb" xml:space="preserve">header_list</spanx> by splitting <spanx style="verb" xml:space="preserve">header_value</spanx> on “,” characters.</t><t>For each <spanx style="verb" xml:space="preserve">header_item</spanx> in <spanx style="verb" xml:space="preserve">header_list</spanx>:  <list style="format %d)" counter="l"><t>Remove leading and trailing WSP characters in <spanx style="verb" xml:space="preserve">header_item</spanx>.</t><t>If the value of <spanx style="verb" xml:space="preserve">parameter_value</spanx> is character-for-character present as a substring of <spanx style="verb" xml:space="preserve">header_value</spanx>, return “1”.</t></list></t><t>Return “0”.</t></list></t><t>For example, the Key:</t><figure title="" suppress-title="false" align="left" alt="" width="" height=""><artwork type="example" xml:space="preserve" name="" align="left" alt="" width="" height=""><![CDATA[

Key: Abc;substr=bennet
]]></artwork></figure><t>Would return “1” for the following header field values:</t><figure title="" suppress-title="false" align="left" alt="" width="" height=""><artwork type="example" xml:space="preserve" name="" align="left" alt="" width="" height=""><![CDATA[

Abc: bennet
Abc: foo, bennet
Abc: abennet00
Abc: bar, 99bennet     , abc
Abc: "bennet"
]]></artwork></figure><t>and “0” for these:</t><figure title="" suppress-title="false" align="left" alt="" width="" height=""><artwork type="example" xml:space="preserve" name="" align="left" alt="" width="" height=""><![CDATA[

Abc: theodore
Abc: joe, sam
Abc: Bennet
Abc: Ben net
]]></artwork></figure></section><section anchor="param" toc="default" title="param"><t>The “param” parameter considers the request header field as a list of key=value parameters, and
uses the nominated key’s value as the secondary cache key.</t><t>Its value’s syntax is:</t><figure title="" suppress-title="false" align="left" alt="" width="" height=""><artwork type="abnf7230" xml:space="preserve" name="" align="left" alt="" width="" height=""><![CDATA[

param  = ( token / quoted-string )
]]></artwork></figure><t>To process a list of header fields against a param parameter, follow these steps (or their
equivalent):</t><t><list style="format %d)" counter="m"><t>Let <spanx style="verb" xml:space="preserve">header_list</spanx> be an empty list.</t><t>Create <spanx style="verb" xml:space="preserve">header_list_tmp1</spanx> by splitting header_value on “,” characters.</t><t>For each <spanx style="verb" xml:space="preserve">header_item_tmp1</spanx> in <spanx style="verb" xml:space="preserve">header_list_tmp1</spanx>:  <list style="format %d)" counter="n"><t>Create <spanx style="verb" xml:space="preserve">header_list_tmp2</spanx> by splitting <spanx style="verb" xml:space="preserve">header_item_tmp1</spanx> on “;” characters.</t><t>For each <spanx style="verb" xml:space="preserve">header_item_tmp2</spanx> in <spanx style="verb" xml:space="preserve">header_list_tmp2</spanx>:      <list style="format %d)" counter="o"><t>Remove leading and trailing WSP from <spanx style="verb" xml:space="preserve">header_item_tmp2</spanx>.</t><t>Append <spanx style="verb" xml:space="preserve">header_item_tmp2</spanx> to header_list.</t></list></t></list></t><t>For each <spanx style="verb" xml:space="preserve">header_item</spanx> in <spanx style="verb" xml:space="preserve">header_list</spanx>:  <list style="format %d)" counter="p"><t>If the “=” character does not occur within <spanx style="verb" xml:space="preserve">header_item</spanx>, skip to the next <spanx style="verb" xml:space="preserve">header_item</spanx>.</t><t>Let <spanx style="verb" xml:space="preserve">item_name</spanx> be the string occurring before the first “=” character in <spanx style="verb" xml:space="preserve">header_item</spanx>.</t><t>If <spanx style="verb" xml:space="preserve">item_name</spanx> does not case-insensitively match <spanx style="verb" xml:space="preserve">parameter_value</spanx>, skip to the next <spanx style="verb" xml:space="preserve">header_item</spanx>.</t><t>Return the string occurring after the first “=” character in <spanx style="verb" xml:space="preserve">header_item</spanx>.</t></list></t><t>Return the empty string.</t></list></t><t>Note that steps 2 and 3 accommodate semicolon-separated values, so that it can be used with the Cookie request header field.</t><t>For example, the Key:</t><figure title="" suppress-title="false" align="left" alt="" width="" height=""><artwork type="example" xml:space="preserve" name="" align="left" alt="" width="" height=""><![CDATA[

Key: Def;param=liam
]]></artwork></figure><t>The following headers would return the string (surrounded in single quotes) indicated:</t><figure title="" suppress-title="false" align="left" alt="" width="" height=""><artwork type="example" xml:space="preserve" name="" align="left" alt="" width="" height=""><![CDATA[

Def: liam=123           // '123'
Def: mno=456            // ''
Def:                    // ''
Def: abc=123; liam=890  // '890'
Def: liam="678"         // '"678"'
]]></artwork></figure></section></section></section><section anchor="iana" toc="default" title="IANA Considerations"><t>This specification defines the HTTP Key Parameter Registry, maintained at
<eref target="http://www.iana.org/assignments/http-parameters/http-parameters.xhtml#key">http://www.iana.org/assignments/http-parameters/http-parameters.xhtml#key</eref>.</t><section anchor="procedure" toc="default" title="Procedure"><t>Key Parameter registrations MUST include the following fields:</t><t><list style="symbols"><t>Parameter Name: [name]</t><t>Reference: [Pointer to specification text]</t></list></t><t>Values to be added to this namespace require IETF Review (see Section 4.1 of <xref target="RFC5226" format="default"/>) and MUST
conform to the purpose of content coding defined in this section.</t></section><section anchor="registrations" toc="default" title="Registrations"><t>This specification makes the following entries in the HTTP Key Parameter Registry:</t><texttable title="" suppress-title="false" align="center" style="full"><ttcol align="left">Parameter Name</ttcol><ttcol align="left">Reference</ttcol><c>div</c><c><xref target="div" format="default"/></c><c>partition</c><c><xref target="partition" format="default"/></c><c>match</c><c><xref target="match" format="default"/></c><c>substr</c><c><xref target="substr" format="default"/></c><c>param</c><c><xref target="param" format="default"/></c></texttable></section></section><section anchor="security-considerations" toc="default" title="Security Considerations"><t>Because Key is an alternative to Vary, it is possible for caches to behave differently based upon
whether they implement Key. Likewise, because support for any one Key parameter is not required, it
is possible for different implementations of Key to behave differently. In both cases, an attacker
might be able to exploit these differences.</t><t>This risk is mitigated by the requirement to fall back to Vary when unsupported parameters are
encountered, coupled with the requirement that servers that use Key also include a relevant Vary
header.</t><t>An attacker with the ability to inject response headers might be able to perform a cache poisoning
attack that tailors a response to a specific user (e.g., by Keying to a Cookie that’s specific to
them). While the attack is still possible without Key, the ability to tailor is new.</t><t>When implemented, Key might result in a larger number of stored responses for a given resource in
caches; this, in turn, might be used to create an attack upon the cache itself. Good cache
replacement algorithms and denial of service monitoring in cache implementations are reasonable
mitigations against this risk.</t></section></middle><back><references title="Normative References"><reference anchor="RFC2119" target="http://www.rfc-editor.org/info/rfc2119"><front><title>Key words for use in RFCs to Indicate Requirement Levels</title><author initials="S." surname="Bradner" fullname="S. Bradner"><organization/></author><date year="1997" month="March"/><abstract><t>In many standards track documents several words are used to signify the requirements in the specification.  These words are often capitalized. This document defines these words as they should be interpreted in IETF documents.  This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t></abstract></front><seriesInfo name="BCP" value="14"/><seriesInfo name="RFC" value="2119"/><seriesInfo name="DOI" value="10.17487/RFC2119"/></reference><reference anchor="RFC5234" target="http://www.rfc-editor.org/info/rfc5234"><front><title>Augmented BNF for Syntax Specifications: ABNF</title><author initials="D." surname="Crocker" fullname="D. Crocker" role="editor"><organization/></author><author initials="P." surname="Overell" fullname="P. Overell"><organization/></author><date year="2008" month="January"/><abstract><t>Internet technical specifications often need to define a formal syntax.  Over the years, a modified version of Backus-Naur Form (BNF), called Augmented BNF (ABNF), has been popular among many Internet specifications.  The current specification documents ABNF. It balances compactness and simplicity with reasonable representational power.  The differences between standard BNF and ABNF involve naming rules, repetition, alternatives, order-independence, and value ranges.  This specification also supplies additional rule definitions and encoding for a core lexical analyzer of the type common to several Internet specifications.  [STANDARDS-TRACK]</t></abstract></front><seriesInfo name="STD" value="68"/><seriesInfo name="RFC" value="5234"/><seriesInfo name="DOI" value="10.17487/RFC5234"/></reference><reference anchor="RFC7230" target="http://www.rfc-editor.org/info/rfc7230"><front><title>Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing</title><author initials="R." surname="Fielding" fullname="R. Fielding" role="editor"><organization/></author><author initials="J." surname="Reschke" fullname="J. Reschke" role="editor"><organization/></author><date year="2014" month="June"/><abstract><t>The Hypertext Transfer Protocol (HTTP) is a stateless application-level protocol for distributed, collaborative, hypertext information systems.  This document provides an overview of HTTP architecture and its associated terminology, defines the "http" and "https" Uniform Resource Identifier (URI) schemes, defines the HTTP/1.1 message syntax and parsing requirements, and describes related security concerns for implementations.</t></abstract></front><seriesInfo name="RFC" value="7230"/><seriesInfo name="DOI" value="10.17487/RFC7230"/></reference><reference anchor="RFC7231" target="http://www.rfc-editor.org/info/rfc7231"><front><title>Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content</title><author initials="R." surname="Fielding" fullname="R. Fielding" role="editor"><organization/></author><author initials="J." surname="Reschke" fullname="J. Reschke" role="editor"><organization/></author><date year="2014" month="June"/><abstract><t>The Hypertext Transfer Protocol (HTTP) is a stateless \%application- level protocol for distributed, collaborative, hypertext information systems.  This document defines the semantics of HTTP/1.1 messages, as expressed by request methods, request header fields, response status codes, and response header fields, along with the payload of messages (metadata and body content) and mechanisms for content negotiation.</t></abstract></front><seriesInfo name="RFC" value="7231"/><seriesInfo name="DOI" value="10.17487/RFC7231"/></reference><reference anchor="RFC7234" target="http://www.rfc-editor.org/info/rfc7234"><front><title>Hypertext Transfer Protocol (HTTP/1.1): Caching</title><author initials="R." surname="Fielding" fullname="R. Fielding" role="editor"><organization/></author><author initials="M." surname="Nottingham" fullname="M. Nottingham" role="editor"><organization/></author><author initials="J." surname="Reschke" fullname="J. Reschke" role="editor"><organization/></author><date year="2014" month="June"/><abstract><t>The Hypertext Transfer Protocol (HTTP) is a stateless \%application- level protocol for distributed, collaborative, hypertext information systems.  This document defines HTTP caches and the associated header fields that control cache behavior or indicate cacheable response messages.</t></abstract></front><seriesInfo name="RFC" value="7234"/><seriesInfo name="DOI" value="10.17487/RFC7234"/></reference></references><references title="Informative References"><reference anchor="RFC5226" target="http://www.rfc-editor.org/info/rfc5226"><front><title>Guidelines for Writing an IANA Considerations Section in RFCs</title><author initials="T." surname="Narten" fullname="T. Narten"><organization/></author><author initials="H." surname="Alvestrand" fullname="H. Alvestrand"><organization/></author><date year="2008" month="May"/><abstract><t>Many protocols make use of identifiers consisting of constants and other well-known values.  Even after a protocol has been defined and deployment has begun, new values may need to be assigned (e.g., for a new option type in DHCP, or a new encryption or authentication transform for IPsec).  To ensure that such quantities have consistent values and interpretations across all implementations, their assignment must be administered by a central authority.  For IETF protocols, that role is provided by the Internet Assigned Numbers Authority (IANA).</t><t>In order for IANA to manage a given namespace prudently, it needs guidelines describing the conditions under which new values can be assigned or when modifications to existing values can be made.  If IANA is expected to play a role in the management of a namespace, IANA must be given clear and concise instructions describing that role.  This document discusses issues that should be considered in formulating a policy for assigning values to a namespace and provides guidelines for authors on the specific text that must be included in documents that place demands on IANA.</t><t>This document obsoletes RFC 2434.  This document specifies an Internet Best  Current Practices for the Internet Community, and requests discussion and  suggestions for improvements.</t></abstract></front><seriesInfo name="BCP" value="26"/><seriesInfo name="RFC" value="5226"/><seriesInfo name="DOI" value="10.17487/RFC5226"/></reference><reference anchor="RFC6265" target="http://www.rfc-editor.org/info/rfc6265"><front><title>HTTP State Management Mechanism</title><author initials="A." surname="Barth" fullname="A. Barth"><organization/></author><date year="2011" month="April"/><abstract><t>This document defines the HTTP Cookie and Set-Cookie header fields. These header fields can be used by HTTP servers to store state (called cookies) at HTTP user agents, letting the servers maintain a stateful session over the mostly stateless HTTP protocol.  Although cookies have many historical infelicities that degrade their security and privacy, the Cookie and Set-Cookie header fields are widely used on the Internet.  This document obsoletes RFC 2965.  [STANDARDS-TRACK]</t></abstract></front><seriesInfo name="RFC" value="6265"/><seriesInfo name="DOI" value="10.17487/RFC6265"/></reference></references><section anchor="acknowledgements" toc="default" title="Acknowledgements"><t>Thanks to Ilya Grigorik, Amos Jeffries and Yoav Weiss for their feedback.</t></section><section anchor="changes" toc="default" title="Changes"><section anchor="since-00" toc="default" title="Since -00"><t><list style="symbols"><t>Issue 108 (field-name cardinality) closed with no action.</t><t>Issue 104 (Support “Or” operator) closed with no action.</t><t>Issue 107 (Whitespace requirement) addressed by allowing whitespace around parameters.</t><t>Issue 106 (Policy for Key parameter registry) closed with no action.</t></list></t></section></section></back></rfc>
