draft-ietf-httpbis-variants-05.txt   draft-ietf-httpbis-variants-latest.txt 
HTTP Working Group M. Nottingham HTTP Working Group M. Nottingham
Internet-Draft Fastly Internet-Draft Fastly
Updates: 7234 (if approved) March 25, 2019 Updates: 7234 (if approved) October 19, 2019
Intended status: Standards Track Intended status: Standards Track
Expires: September 26, 2019 Expires: April 21, 2020
HTTP Representation Variants HTTP Representation Variants
draft-ietf-httpbis-variants-05 draft-ietf-httpbis-variants-latest
Abstract Abstract
This specification introduces an alternative way to communicate a This specification introduces an alternative way to communicate a
secondary cache key for a HTTP resource, using the HTTP "Variants" secondary cache key for a HTTP resource, using the HTTP "Variants"
and "Variant-Key" response header fields. Its aim is to make HTTP and "Variant-Key" response header fields. Its aim is to make HTTP
proactive content negotiation more cache-friendly. proactive content negotiation more cache-friendly.
Note to Readers Note to Readers
skipping to change at page 1, line 49 skipping to change at page 1, line 49
Internet-Drafts are working documents of the Internet Engineering Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF). Note that other groups may also distribute Task Force (IETF). Note that other groups may also distribute
working documents as Internet-Drafts. The list of current Internet- working documents as Internet-Drafts. The list of current Internet-
Drafts is at https://datatracker.ietf.org/drafts/current/. Drafts is at https://datatracker.ietf.org/drafts/current/.
Internet-Drafts are draft documents valid for a maximum of six months Internet-Drafts are draft documents valid for a maximum of six months
and may be updated, replaced, or obsoleted by other documents at any and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress." material or to cite them other than as "work in progress."
This Internet-Draft will expire on September 26, 2019. This Internet-Draft will expire on April 21, 2020.
Copyright Notice Copyright Notice
Copyright (c) 2019 IETF Trust and the persons identified as the Copyright (c) 2019 IETF Trust and the persons identified as the
document authors. All rights reserved. document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents Provisions Relating to IETF Documents
(https://trustee.ietf.org/license-info) in effect on the date of (https://trustee.ietf.org/license-info) in effect on the date of
publication of this document. Please review these documents publication of this document. Please review these documents
carefully, as they describe your rights and restrictions with respect carefully, as they describe your rights and restrictions with respect
to this document. Code Components extracted from this document must to this document. Code Components extracted from this document must
include Simplified BSD License text as described in Section 4.e of include Simplified BSD License text as described in Section 4.e of
the Trust Legal Provisions and are provided without warranty as the Trust Legal Provisions and are provided without warranty as
described in the Simplified BSD License. described in the Simplified BSD License.
Table of Contents Table of Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1. Notational Conventions . . . . . . . . . . . . . . . . . 4 1.1. Notational Conventions . . . . . . . . . . . . . . . . . 5
2. The "Variants" HTTP Header Field . . . . . . . . . . . . . . 5 2. The "Variants" HTTP Header Field . . . . . . . . . . . . . . 5
2.1. Relationship to Vary . . . . . . . . . . . . . . . . . . 7 2.1. Relationship to Vary . . . . . . . . . . . . . . . . . . 7
3. The "Variant-Key" HTTP Header Field . . . . . . . . . . . . . 7 3. The "Variant-Key" HTTP Header Field . . . . . . . . . . . . . 7
4. Cache Behaviour . . . . . . . . . . . . . . . . . . . . . . . 9 4. Cache Behaviour . . . . . . . . . . . . . . . . . . . . . . . 9
4.1. Compute Possible Keys . . . . . . . . . . . . . . . . . . 10 4.1. Compute Possible Keys . . . . . . . . . . . . . . . . . . 10
4.2. Check Vary . . . . . . . . . . . . . . . . . . . . . . . 11 4.2. Check Vary . . . . . . . . . . . . . . . . . . . . . . . 11
4.3. Example of Cache Behaviour . . . . . . . . . . . . . . . 11 4.3. Example of Cache Behaviour . . . . . . . . . . . . . . . 12
4.3.1. A Variant Missing From the Cache . . . . . . . . . . 12 4.3.1. A Variant Missing From the Cache . . . . . . . . . . 12
4.3.2. Variants That Don't Overlap the Client's Request . . 13 4.3.2. Variants That Don't Overlap the Client's Request . . 13
5. Origin Server Behaviour . . . . . . . . . . . . . . . . . . . 13 5. Origin Server Behaviour . . . . . . . . . . . . . . . . . . . 13
5.1. Examples . . . . . . . . . . . . . . . . . . . . . . . . 14 5.1. Examples . . . . . . . . . . . . . . . . . . . . . . . . 14
5.1.1. Single Variant . . . . . . . . . . . . . . . . . . . 14 5.1.1. Single Variant . . . . . . . . . . . . . . . . . . . 14
5.1.2. Multiple Variants . . . . . . . . . . . . . . . . . . 15 5.1.2. Multiple Variants . . . . . . . . . . . . . . . . . . 15
5.1.3. Partial Coverage . . . . . . . . . . . . . . . . . . 15 5.1.3. Partial Coverage . . . . . . . . . . . . . . . . . . 15
6. Defining Content Negotiation Using Variants . . . . . . . . . 16 6. Defining Content Negotiation Using Variants . . . . . . . . . 16
7. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 16 7. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 16
8. Security Considerations . . . . . . . . . . . . . . . . . . . 17 8. Security Considerations . . . . . . . . . . . . . . . . . . . 17
9. References . . . . . . . . . . . . . . . . . . . . . . . . . 17 9. References . . . . . . . . . . . . . . . . . . . . . . . . . 17
9.1. Normative References . . . . . . . . . . . . . . . . . . 17 9.1. Normative References . . . . . . . . . . . . . . . . . . 17
9.2. Informative References . . . . . . . . . . . . . . . . . 18 9.2. Informative References . . . . . . . . . . . . . . . . . 18
9.3. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 18 9.3. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 19
Appendix A. Variants for Existing Content Negotiation Mechanisms 19 Appendix A. Variants for Existing Content Negotiation Mechanisms 19
A.1. Accept . . . . . . . . . . . . . . . . . . . . . . . . . 19 A.1. Accept . . . . . . . . . . . . . . . . . . . . . . . . . 19
A.2. Accept-Encoding . . . . . . . . . . . . . . . . . . . . . 20 A.2. Accept-Encoding . . . . . . . . . . . . . . . . . . . . . 20
A.3. Accept-Language . . . . . . . . . . . . . . . . . . . . . 20 A.3. Accept-Language . . . . . . . . . . . . . . . . . . . . . 21
Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . 21 A.4. Cookie . . . . . . . . . . . . . . . . . . . . . . . . . 21
Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 21 Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . 23
Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 23
1. Introduction 1. Introduction
HTTP proactive content negotiation ([RFC7231], Section 3.4.1) is HTTP proactive content negotiation ([RFC7231], Section 3.4.1) is
seeing renewed interest, both for existing request headers like seeing renewed interest, both for existing request headers like
Accept-Language and for newer ones (for example, see Accept-Language and for newer ones (for example, see
[I-D.ietf-httpbis-client-hints]). [I-D.ietf-httpbis-client-hints]).
Successfully reusing negotiated responses that have been stored in a Successfully reusing negotiated responses that have been stored in a
HTTP cache requires establishment of a secondary cache key HTTP cache requires establishment of a secondary cache key
([RFC7234], Section 4.1). Currently, the Vary header ([RFC7231], ([RFC7234], Section 4.1). Currently, the Vary header ([RFC7231],
Section 7.1.4) does this by nominating a set of request headers. Section 7.1.4) does this by nominating a set of request headers.
Their values collectively form the secondary cache key for a given
response.
HTTP's caching model allows a certain amount of latitude in HTTP's caching model allows a certain amount of latitude in
normalising those request header field values, so as to increase the normalising those request header field values, so as to increase the
chances of a cache hit while still respecting the semantics of that chances of a cache hit while still respecting the semantics of that
header. However, normalisation is not formally defined, leading to header. However, normalisation is not formally defined, leading to
divergence in cache behaviours. infrequent implementation in cache, and divergence of behaviours when
it is.
Even when the headers' semantics are understood, a cache does not Even when the headers' semantics are understood, a cache does not
know enough about the possible alternative representations available know enough about the possible alternative representations available
on the origin server to make an appropriate decision. on the origin server to make an appropriate decision.
For example, if a cache has stored the following request/response For example, if a cache has stored the following request/response
pair: pair:
GET /foo HTTP/1.1 GET /foo HTTP/1.1
Host: www.example.com Host: www.example.com
skipping to change at page 4, line 10 skipping to change at page 4, line 14
This specification introduces the HTTP Variants response header field This specification introduces the HTTP Variants response header field
(Section 2) to enumerate the available variant representations on the (Section 2) to enumerate the available variant representations on the
origin server, to provide clients and caches with enough information origin server, to provide clients and caches with enough information
to properly satisfy requests - either by selecting a response from to properly satisfy requests - either by selecting a response from
cache or by forwarding the request towards the origin - by following cache or by forwarding the request towards the origin - by following
the algorithm defined in Section 4. the algorithm defined in Section 4.
Its companion Variant-Key response header field (Section 3) indicates Its companion Variant-Key response header field (Section 3) indicates
the applicable key(s) that the response is associated with, so that the applicable key(s) that the response is associated with, so that
it can be reliably reused in the future. When this specification is it can be reliably reused in the future. Effectively, it allows the
in use, the example above might become: specification of a request header field to define how it affects the
secondary cache key.
When this specification is in use, the example above might become:
GET /foo HTTP/1.1 GET /foo HTTP/1.1
Host: www.example.com Host: www.example.com
Accept-Language: en;q=0.5, fr;q=1.0 Accept-Language: en;q=0.5, fr;q=1.0
HTTP/1.1 200 OK HTTP/1.1 200 OK
Content-Type: text/html Content-Type: text/html
Content-Language: en Content-Language: en
Vary: Accept-Language Vary: Accept-Language
Variants: Accept-Language;de;en;jp Variants: Accept-Language;de;en;jp
skipping to change at page 5, line 9 skipping to change at page 5, line 17
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
"OPTIONAL" in this document are to be interpreted as described in BCP "OPTIONAL" in this document are to be interpreted as described in BCP
14 [RFC2119] [RFC8174] when, and only when, they appear in all 14 [RFC2119] [RFC8174] when, and only when, they appear in all
capitals, as shown here. capitals, as shown here.
This specification uses the Augmented Backus-Naur Form (ABNF) This specification uses the Augmented Backus-Naur Form (ABNF)
notation of [RFC5234] but relies on Structured Headers from notation of [RFC5234] but relies on Structured Headers from
[I-D.ietf-httpbis-header-structure] for parsing. [I-D.ietf-httpbis-header-structure] for parsing.
Additionally, it uses the "field-name" rule from [RFC7230], and Additionally, it uses the "field-name" rule from [RFC7230], "type",
"type", "subtype", "content-coding" and "language-range" from "subtype", "content-coding" and "language-range" from [RFC7231], and
[RFC7231]. "cookie-name" from [RFC6265].
2. The "Variants" HTTP Header Field 2. The "Variants" HTTP Header Field
The Variants HTTP response header field indicates what The Variants HTTP response header field indicates what
representations are available for a given resource at the time that representations are available for a given resource at the time that
the response is produced, by enumerating the request header fields the response is produced, by enumerating the request header fields
that it varies on, along with the values that are available for each. that it varies on, along with a representation of the values that are
available for each.
Variants is a Structured Header [I-D.ietf-httpbis-header-structure]. Variants is a Structured Header [I-D.ietf-httpbis-header-structure].
Its value MUST be a list-of-lists (Section 3.3 of Its value MUST be a Dictionary (Section 3.2 of
[I-D.ietf-httpbis-header-structure]) whose members are strings [I-D.ietf-httpbis-header-structure]). Its ABNF is:
(Section 3.8 of [I-D.ietf-httpbis-header-structure]) or tokens
(Section 3.9 of [I-D.ietf-httpbis-header-structure]). Its ABNF is:
Variants = sh-list-of-lists Variants = sh-dict
If Structured Header parsing fails or a list-member has the wrong Its member-names are tokens (Section 3.7 of
type, the client MUST treat the representation as having no Variants [I-D.ietf-httpbis-header-structure]), each representing the field-
header field. names of a request header that is part of the secondary cache key.
The member-values are a list of strings (Section 3.6 of
[I-D.ietf-httpbis-header-structure]) or tokens that convey
representations of potential values for that header field, hereafter
referred to as "available-values".
The Variants header field represents an ordered list of "variant- If Structured Header parsing fails or a member's value does have the
axes", each of which consists of a request header "field-name" string structure outlined above, the client MUST treat the representation as
and a list of "available-value" strings. Each inner-list in the having no Variants header field.
Variants header field value is parsed into a variant-axis. The first
list-member of the inner-list is interpreted as the field-name, and
the remaining list-members are the available-values. Any list-member
that is a token (Section 3.9 of [I-D.ietf-httpbis-header-structure])
is interpreted as a string containing the same characters.
Field-names in the Variants header field value MUST match the field- Note that a available-value that is a token is interpreted as a
name production (Section 3.2 of [RFC7230]). Clients receiving an string containing the same characters, and vice versa.
invalid field-name MUST NOT match it to any content negotiating
mechanism. Field-names in the member-names MUST match the field-name production
(Section 3.2 of [RFC7230]). Clients receiving an invalid field-name
MUST NOT match it to any content negotiating mechanism.
So, given this example header field: So, given this example header field:
Variants: Accept-Encoding;gzip Variants: Accept-Encoding=(gzip)
a recipient can infer that the only content-coding available for that a recipient can infer that the only content-coding available for that
resource is "gzip" (along with the "identity" non-encoding; see resource is "gzip" (along with the "identity" non-encoding; see
Appendix A.2). Appendix A.2).
Given: Given:
Variants: accept-encoding Variants: accept-encoding=()
a recipient can infer that no content-codings (beyond identity) are a recipient can infer that no content-codings (beyond identity) are
supported. Note that as always, field-name is case-insensitive. supported. Note that as always, field-name is case-insensitive.
A more complex example: A more complex example:
Variants: Accept-Encoding;gzip;br, Accept-Language;en ;fr Variants: Accept-Encoding=(gzip br), Accept-Language=(en fr)
Here, recipients can infer that two content-codings in addition to Here, recipients can infer that two content-codings in addition to
"identity" are available, as well as two content languages. Note "identity" are available, as well as two content languages. Note
that, as with all Structured Header lists, they might occur in the that, as with all Structured Header dictionaries, they might occur in
same header field or separately, like this: the same header field or separately, like this:
Variants: Accept-Encoding;gzip;brotli Variants: Accept-Encoding=(gzip brotli)
Variants: Accept-Language;en ;fr Variants: Accept-Language=(en fr)
The ordering of available-values after the field-name is significant, The ordering of available-values is significant, as it might be used
as it might be used by the header's algorithm for selecting a by the header's algorithm for selecting a response (in this example,
response (in this example, the first language is the default; see the first language is the default; see Appendix A.3).
Appendix A.3).
The ordering of the request header fields themselves indicates The ordering of the request header fields themselves indicates
descending application of preferences; in the example above, a cache descending application of preferences; in the example above, a cache
that has all of the possible permutations stored will honour the that has all of the possible permutations stored will honour the
client's preferences for Accept-Encoding before honouring Accept- client's preferences for Accept-Encoding before honouring Accept-
Language. Language.
Origin servers SHOULD consistently send Variant header fields on all Origin servers SHOULD consistently send Variant header fields on all
cacheable (as per [RFC7234], Section 3) responses for a resource, cacheable (as per [RFC7234], Section 3) responses for a resource,
since its absence will trigger caches to fall back to Vary since its absence will trigger caches to fall back to Vary
skipping to change at page 7, line 27 skipping to change at page 7, line 32
See Section 5.1.3 for an example. See Section 5.1.3 for an example.
In practice, implementation of Vary varies considerably. As a In practice, implementation of Vary varies considerably. As a
result, cache efficiency might drop considerably when Variants does result, cache efficiency might drop considerably when Variants does
not contain all of the headers referenced by Vary, because some not contain all of the headers referenced by Vary, because some
implementations might choose to disable Variants processing when this implementations might choose to disable Variants processing when this
is the case. is the case.
3. The "Variant-Key" HTTP Header Field 3. The "Variant-Key" HTTP Header Field
The Variant-Key HTTP response header field identifies a set of The Variant-Key HTTP response header field identifies one or more
variants provided by the representation it occurs within. A variant sets of available-values that identify the secondary cache key(s)
is identified by a selection of one available-value from each that the response it occurs within are associated with.
variant-axis from the Variants header field.
Variant-Key is a Structured Header Variant-Key is a Structured Header
[I-D.ietf-httpbis-header-structure]. Its value MUST be a list-of- [I-D.ietf-httpbis-header-structure]. Its value MUST be a list
lists (Section 3.3 of [I-D.ietf-httpbis-header-structure]) whose (Section 3.1 of [I-D.ietf-httpbis-header-structure]) whose members
members are strings (Section 3.8 of are lists of strings (Section 3.6 of
[I-D.ietf-httpbis-header-structure]) or tokens (Section 3.9 of [I-D.ietf-httpbis-header-structure]) or tokens (Section 3.7 of
[I-D.ietf-httpbis-header-structure]). Its ABNF is: [I-D.ietf-httpbis-header-structure]). Its ABNF is:
Variant-Key = sh-list-of-lists Variant-Key = sh-list
If Structured Header parsing fails or a list-member has the wrong Each member MUST be a list, and MUST itself have the same number of
type, the client MUST treat the representation as having no Variant- members as there are members of the representation's Variants header
Key header field. field. If not, the client MUST treat the representation as having no
Variant-Key header field.
Each inner-list MUST have the same number of list-members as there Each member identifies a list of available-values corresponding to
are variant-axes in the representation's Variants header field. If the header field-names in the Variants header field, thereby
not, the client MUST treat the representation as having no Variant- identifying a secondary cache key that can be used with this
Key header field. response. These available-values do not need to explicitly appear in
the Variants header field; they can be interpreted by the algorithm
specific to processing that field. For example, Accept-Encoding
defines an implicit "identity" available-value (Appendix A.2).
Each list-member is treated as identifying an available-value for the Each inner-list member is treated as identifying an available-value
corresponding variant-axis' field-name. Any list-member that is a for the corresponding variant-axis' field-name. Any list-member that
token (Section 3.9 of [I-D.ietf-httpbis-header-structure]) is is a token (Section 3.9 of [I-D.ietf-httpbis-header-structure]) is
interpreted as a string containing the same characters. These interpreted as a string containing the same characters.
available-values do not need to explicitly appear in the Variants
header field. For example, Accept-Encoding defines an implicit
"identity" available-value (Appendix A.2).
For example: For example:
Variants: Accept-Encoding;gzip;br, Accept-Language;en ;fr Variants: Accept-Encoding=(gzip br), Accept-Language=(en fr)
Variant-Key: gzip;fr Variant-Key: (gzip fr)
This header pair indicates that the representation has a "gzip" This header pair indicates that the representation has a "gzip"
content-coding and "fr" content-language. content-coding and "fr" content-language.
If the response can be used to satisfy more than one request, they If the response can be used to satisfy more than one request, they
can be listed in additional members. For example: can be listed in additional members. For example:
Variants: Accept-Encoding;gzip;br, Accept-Language;en ;fr Variants: Accept-Encoding=(gzip br), Accept-Language=(en fr)
Variant-Key: gzip;fr, "identity";fr Variant-Key: (gzip fr), ("identity" fr)
indicates that this response can be used for requests whose Accept- indicates that this response can be used for requests whose Accept-
Encoding algorithm selects "gzip" or "identity", as long as the Encoding algorithm selects "gzip" or "identity", as long as the
Accept-Language algorithm selects "fr" - perhaps because there is no Accept-Language algorithm selects "fr" - perhaps because there is no
gzip-compressed French representation. gzip-compressed French representation.
When more than one Variant-Key value is in a response, the first one When more than one Variant-Key value is in a response, the first one
present MUST correspond to the request that caused that response to present MUST correspond to the request that caused that response to
be generated. be generated. For example:
Parsing is strict. For example:
Variants: Accept-Encoding;gzip;br, Accept-Language;en ;fr Variants: Accept-Encoding=(gzip br), Accept-Language=(en fr)
Variant-Key: gzip;fr, identity;fr, br;fr;oops Variant-Key: (gzip fr), (identity fr), (br fr oops)
is treated as if the Variant-Key header were completely absent, which is treated as if the Variant-Key header were completely absent, which
will tend to disable caching for the representation that contains it. will tend to disable caching for the representation that contains it.
Note that in Note that in
Variant-Key: gzip ;fr Variant-Key: (gzip fr)
Variant-Key: "gzip ";fr Variant-Key: ("gzip " fr)
The whitespace after "gzip" in the first header field value is The whitespace after "gzip" in the first header field value is
excluded by the token parsing algorithm, but the whitespace in the excluded by the token parsing algorithm, but the whitespace in the
second header field value is included by the string parsing second header field value is included by the string parsing
algorithm. This will likely cause the second header field value to algorithm. This will likely cause the second header field value to
fail to match client requests. fail to match client requests.
_RFC EDITOR: Please remove the next paragraph before publication._ _RFC EDITOR: Please remove the next paragraph before publication._
Implementations of drafts of this specification MUST implement an Implementations of drafts of this specification MUST implement an
HTTP header field named "Variant-Key-##" instead of the "Variant-Key" HTTP header field named "Variant-Key-##" instead of the "Variant-Key"
header field specified by the final RFC, with "##" replaced by the header field specified by the final RFC, with "##" replaced by the
draft number being implemented. For example, implementations of draft number being implemented. For example, implementations of
draft-ietf-httpbis-variants-05 would implement "Variant-Key-05". draft-ietf-httpbis-variants-05 would implement "Variant-Key-05".
4. Cache Behaviour 4. Cache Behaviour
Caches that implement the Variants header field and the relevant Caches that implement the Variants header field and the relevant
semantics of the field-names it contains can use that knowledge to semantics of the field-names it contains can use that knowledge to
either select an appropriate stored representation, or forward the either select an appropriate stored representation, or forward the
request if no appropriate representation is stored. request if no appropriate representation is stored.
They do so by running this algorithm (or its functional equivalent) They do so by running this algorithm (or its functional equivalent)
upon receiving a request: upon receiving a request:
Given incoming-request (a mapping of field-names to lists of field Given incoming-request (a mapping of field-names to field-values,
values), and stored-responses (a list of stored responses suitable after being combined as allowed by Section 3.2.2 of [RFC7230]), and
for reuse as defined in Section 4 of [RFC7234], excepting the stored-responses (a list of stored responses suitable for reuse as
requirement to calculate a secondary cache key): defined in Section 4 of [RFC7234], excepting the requirement to
calculate a secondary cache key):
1. If stored-responses is empty, return an empty list. 1. If stored-responses is empty, return an empty list.
2. Order stored-responses by the "Date" header field, most recent to 2. Order stored-responses by the "Date" header field, most recent to
least recent. least recent.
3. Let sorted-variants be an empty list. 3. Let sorted-variants be an empty list.
4. If the freshest member of stored-responses (as per [RFC7234], 4. If the freshest member of stored-responses (as per [RFC7234],
Section 4.2) has one or more "Variants" header field(s) that Section 4.2) has one or more "Variants" header field(s) that
skipping to change at page 9, line 49 skipping to change at page 10, line 10
SHOULD be the most recent response, but MAY be from an older SHOULD be the most recent response, but MAY be from an older
one as long as it is still fresh. one as long as it is still fresh.
2. For each variant-axis in variants-header: 2. For each variant-axis in variants-header:
1. If variant-axis' field-name corresponds to the request 1. If variant-axis' field-name corresponds to the request
header field identified by a content negotiation header field identified by a content negotiation
mechanism that the implementation supports: mechanism that the implementation supports:
1. Let request-value be the field-value associated with 1. Let request-value be the field-value associated with
field-name in incoming-request (after being combined field-name in incoming-request, or null if field-name
as allowed by Section 3.2.2 of [RFC7230]), or null if is not in incoming-request.
field-name is not in incoming-request.
2. Let sorted-values be the result of running the 2. Let sorted-values be the result of running the
algorithm defined by the content negotiation algorithm defined by the content negotiation
mechanism with request-value and variant-axis' mechanism with request-value and variant-axis'
available-values. available-values.
3. Append sorted-values to sorted-variants. 3. Append sorted-values to sorted-variants.
At this point, sorted-variants will be a list of lists, each At this point, sorted-variants will be a list of lists, each
member of the top-level list corresponding to a variant-axis member of the top-level list corresponding to a variant-axis
skipping to change at page 11, line 13 skipping to change at page 11, line 21
this-key and possible-keys. this-key and possible-keys.
4. Return possible-keys. 4. Return possible-keys.
4.2. Check Vary 4.2. Check Vary
This algorithm is an example of how an implementation can meet the This algorithm is an example of how an implementation can meet the
requirement to apply the members of the Vary header field that are requirement to apply the members of the Vary header field that are
not covered by Variants. not covered by Variants.
Given stored-response (a stored response): Given incoming-request (a mapping of field-names to field-values,
after being combined as allowed by Section 3.2.2 of [RFC7230]), and
stored-response (a stored response):
1. Let filtered-vary be the field-value(s) of stored-response's 1. Let filtered-vary be the field-value(s) of stored-response's
"Vary" header field. "Vary" header field.
2. Let processed-variants be a list containing the request header 2. Let processed-variants be a list containing the request header
fields that identify the content negotiation mechanisms supported fields that identify the content negotiation mechanisms supported
by the implementation. by the implementation.
3. Remove any member of filtered-vary that is a case-insensitive 3. Remove any member of filtered-vary that is a case-insensitive
match for a member of processed-variants. match for a member of processed-variants.
skipping to change at page 11, line 44 skipping to change at page 12, line 9
Note that implementation of the Vary header field varies in practice, Note that implementation of the Vary header field varies in practice,
and the algorithm above illustrates only one way to apply it. It is and the algorithm above illustrates only one way to apply it. It is
equally viable to forward the request if there is a request header equally viable to forward the request if there is a request header
listed in Vary but not Variants. listed in Vary but not Variants.
4.3. Example of Cache Behaviour 4.3. Example of Cache Behaviour
For example, if the selected variants-header was: For example, if the selected variants-header was:
Variants: Accept-Language;en;fr;de, Accept-Encoding;gzip;br Variants: Accept-Language=(en fr de), Accept-Encoding=(gzip br)
and the request contained the headers: and the request contained the headers:
Accept-Language: fr;q=1.0, en;q=0.1 Accept-Language: fr;q=1.0, en;q=0.1
Accept-Encoding: gzip Accept-Encoding: gzip
Then the sorted-variants would be: Then the sorted-variants would be:
[ [
["fr", "en"] // prefers French, will accept English ["fr", "en"] // prefers French, will accept English
skipping to change at page 12, line 23 skipping to change at page 12, line 36
[ [
["fr", "gzip"], ["fr", "gzip"],
["fr", "identity"], ["fr", "identity"],
["en", "gzip"], ["en", "gzip"],
["en", "identity"] ["en", "identity"]
] ]
Representing a first preference of a French, gzip'd response. Thus, Representing a first preference of a French, gzip'd response. Thus,
if a cache has a response with: if a cache has a response with:
Variant-Key: fr; gzip Variant-Key: (fr gzip)
it could be used to satisfy the first preference. If not, responses it could be used to satisfy the first preference. If not, responses
corresponding to the other keys could be returned, or the request corresponding to the other keys could be returned, or the request
could be forwarded towards the origin. could be forwarded towards the origin.
4.3.1. A Variant Missing From the Cache 4.3.1. A Variant Missing From the Cache
If the selected variants-header was: If the selected variants-header was:
Variants: Accept-Language;en;fr;de Variants: Accept-Language=(en fr de)
And a request comes in with the following headers: And a request comes in with the following headers:
Accept-Language: de;q=1.0, es;q=0.8 Accept-Language: de;q=1.0, es;q=0.8
Then sorted-variants in Cache Behaviour is: Then sorted-variants in Cache Behaviour is:
[ [
["de"] // prefers German; will not accept English ["de"] // prefers German; will not accept English
] ]
If the cache contains responses with the following Variant-Keys: If the cache contains responses with the following Variant-Keys:
Variant-Key: fr Variant-Key: (fr)
Variant-Key: en Variant-Key: (en)
Then the cache needs to forward the request to the origin server, Then the cache needs to forward the request to the origin server,
since Variants indicates that "de" is available, and that is since Variants indicates that "de" is available, and that is
acceptable to the client. acceptable to the client.
4.3.2. Variants That Don't Overlap the Client's Request 4.3.2. Variants That Don't Overlap the Client's Request
If the selected variants-header was: If the selected variants-header was:
Variants: Accept-Language;en;fr;de Variants: Accept-Language=(en fr de)
And a request comes in with the following headers: And a request comes in with the following headers:
Accept-Language: es;q=1.0, ja;q=0.8 Accept-Language: es;q=1.0, ja;q=0.8
Then sorted-variants in Cache Behaviour are: Then sorted-variants in Cache Behaviour are:
[ [
["en"] ["en"]
] ]
skipping to change at page 14, line 21 skipping to change at page 14, line 34
Given a request/response pair: Given a request/response pair:
GET /clancy HTTP/1.1 GET /clancy HTTP/1.1
Host: www.example.com Host: www.example.com
Accept-Language: en;q=1.0, fr;q=0.5 Accept-Language: en;q=1.0, fr;q=0.5
HTTP/1.1 200 OK HTTP/1.1 200 OK
Content-Type: image/gif Content-Type: image/gif
Content-Language: en Content-Language: en
Cache-Control: max-age=3600 Cache-Control: max-age=3600
Variants: Accept-Language;en;de Variants: Accept-Language=(en de)
Variant-Key: en Variant-Key: (en)
Vary: Accept-Language Vary: Accept-Language
Transfer-Encoding: chunked Transfer-Encoding: chunked
Upon receipt of this response, the cache knows that two Upon receipt of this response, the cache knows that two
representations of this resource are available, one with a language representations of this resource are available, one with a language
of "en", and another whose language is "de". of "en", and another whose language is "de".
Subsequent requests (while this response is fresh) will cause the Subsequent requests (while this response is fresh) will cause the
cache to either reuse this response or forward the request, depending cache to either reuse this response or forward the request, depending
on what the selection algorithm determines. on what the selection algorithm determines.
skipping to change at page 15, line 18 skipping to change at page 15, line 28
GET /murray HTTP/1.1 GET /murray HTTP/1.1
Host: www.example.net Host: www.example.net
Accept-Language: en;q=1.0, fr;q=0.5 Accept-Language: en;q=1.0, fr;q=0.5
Accept-Encoding: gzip, br Accept-Encoding: gzip, br
HTTP/1.1 200 OK HTTP/1.1 200 OK
Content-Type: image/gif Content-Type: image/gif
Content-Language: en Content-Language: en
Content-Encoding: br Content-Encoding: br
Variants: Accept-Language;en;jp;de Variants: Accept-Language=(en jp de)
Variants: Accept-Encoding;br;gzip Variants: Accept-Encoding=(br gzip)
Variant-Key: en;br Variant-Key: (en br)
Vary: Accept-Language, Accept-Encoding Vary: Accept-Language, Accept-Encoding
Transfer-Encoding: chunked Transfer-Encoding: chunked
Here, the cache knows that there are two axes that the response Here, the cache knows that there are two axes that the response
varies upon; language and encoding. Thus, there are a total of nine varies upon; language and encoding. Thus, there are a total of nine
possible representations for the resource (including the identity possible representations for the resource (including the identity
encoding), and the cache needs to consider the selection algorithms encoding), and the cache needs to consider the selection algorithms
for both axes. for both axes.
Upon a subsequent request, if both selection algorithms return a Upon a subsequent request, if both selection algorithms return a
skipping to change at page 16, line 4 skipping to change at page 16, line 9
5.1.3. Partial Coverage 5.1.3. Partial Coverage
Now, consider the previous example, but where only one of the Vary'd Now, consider the previous example, but where only one of the Vary'd
axes (encoding) is listed in Variants: axes (encoding) is listed in Variants:
GET /bar HTTP/1.1 GET /bar HTTP/1.1
Host: www.example.net Host: www.example.net
Accept-Language: en;q=1.0, fr;q=0.5 Accept-Language: en;q=1.0, fr;q=0.5
Accept-Encoding: gzip, br Accept-Encoding: gzip, br
HTTP/1.1 200 OK HTTP/1.1 200 OK
Content-Type: image/gif Content-Type: image/gif
Content-Language: en Content-Language: en
Content-Encoding: br Content-Encoding: br
Variants: Accept-Encoding;br;gzip Variants: Accept-Encoding=(br gzip)
Variant-Key: br Variant-Key: (br)
Vary: Accept-Language, Accept-Encoding Vary: Accept-Language, Accept-Encoding
Transfer-Encoding: chunked Transfer-Encoding: chunked
Here, the cache will need to calculate a secondary cache key as per Here, the cache will need to calculate a secondary cache key as per
[RFC7234], Section 4.1 - but considering only Accept-Language to be [RFC7234], Section 4.1 - but considering only Accept-Language to be
in its field-value - and then continue processing Variants for the in its field-value - and then continue processing Variants for the
set of stored responses that the algorithm described there selects. set of stored responses that the algorithm described there selects.
6. Defining Content Negotiation Using Variants 6. Defining Content Negotiation Using Variants
skipping to change at page 17, line 41 skipping to change at page 17, line 48
Note that the Variants header is not a commitment to make Note that the Variants header is not a commitment to make
representations of a certain nature available; the runtime behaviour representations of a certain nature available; the runtime behaviour
of the server always overrides hints like Variants. of the server always overrides hints like Variants.
9. References 9. References
9.1. Normative References 9.1. Normative References
[I-D.ietf-httpbis-header-structure] [I-D.ietf-httpbis-header-structure]
Nottingham, M. and P. Kamp, "Structured Headers for HTTP", Nottingham, M. and P. Kamp, "Structured Headers for HTTP",
draft-ietf-httpbis-header-structure-09 (work in progress), draft-ietf-httpbis-header-structure-13 (work in progress),
December 2018. August 2019.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119, Requirement Levels", BCP 14, RFC 2119,
DOI 10.17487/RFC2119, March 1997, DOI 10.17487/RFC2119, March 1997,
<https://www.rfc-editor.org/info/rfc2119>. <https://www.rfc-editor.org/info/rfc2119>.
[RFC4647] Phillips, A. and M. Davis, "Matching of Language Tags", [RFC4647] Phillips, A. and M. Davis, "Matching of Language Tags",
BCP 47, RFC 4647, DOI 10.17487/RFC4647, September 2006, BCP 47, RFC 4647, DOI 10.17487/RFC4647, September 2006,
<https://www.rfc-editor.org/info/rfc4647>. <https://www.rfc-editor.org/info/rfc4647>.
[RFC5234] Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax [RFC5234] Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax
Specifications: ABNF", STD 68, RFC 5234, Specifications: ABNF", STD 68, RFC 5234,
DOI 10.17487/RFC5234, January 2008, DOI 10.17487/RFC5234, January 2008,
<https://www.rfc-editor.org/info/rfc5234>. <https://www.rfc-editor.org/info/rfc5234>.
[RFC6265] Barth, A., "HTTP State Management Mechanism", RFC 6265,
DOI 10.17487/RFC6265, April 2011,
<https://www.rfc-editor.org/info/rfc6265>.
[RFC7230] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer [RFC7230] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer
Protocol (HTTP/1.1): Message Syntax and Routing", Protocol (HTTP/1.1): Message Syntax and Routing",
RFC 7230, DOI 10.17487/RFC7230, June 2014, RFC 7230, DOI 10.17487/RFC7230, June 2014,
<https://www.rfc-editor.org/info/rfc7230>. <https://www.rfc-editor.org/info/rfc7230>.
[RFC7231] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer [RFC7231] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer
Protocol (HTTP/1.1): Semantics and Content", RFC 7231, Protocol (HTTP/1.1): Semantics and Content", RFC 7231,
DOI 10.17487/RFC7231, June 2014, DOI 10.17487/RFC7231, June 2014,
<https://www.rfc-editor.org/info/rfc7231>. <https://www.rfc-editor.org/info/rfc7231>.
skipping to change at page 18, line 33 skipping to change at page 18, line 46
<https://www.rfc-editor.org/info/rfc7234>. <https://www.rfc-editor.org/info/rfc7234>.
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
May 2017, <https://www.rfc-editor.org/info/rfc8174>. May 2017, <https://www.rfc-editor.org/info/rfc8174>.
9.2. Informative References 9.2. Informative References
[I-D.ietf-httpbis-client-hints] [I-D.ietf-httpbis-client-hints]
Grigorik, I., "HTTP Client Hints", draft-ietf-httpbis- Grigorik, I., "HTTP Client Hints", draft-ietf-httpbis-
client-hints-06 (work in progress), July 2018. client-hints-07 (work in progress), March 2019.
[RFC2295] Holtman, K. and A. Mutz, "Transparent Content Negotiation [RFC2295] Holtman, K. and A. Mutz, "Transparent Content Negotiation
in HTTP", RFC 2295, DOI 10.17487/RFC2295, March 1998, in HTTP", RFC 2295, DOI 10.17487/RFC2295, March 1998,
<https://www.rfc-editor.org/info/rfc2295>. <https://www.rfc-editor.org/info/rfc2295>.
[RFC3864] Klyne, G., Nottingham, M., and J. Mogul, "Registration [RFC3864] Klyne, G., Nottingham, M., and J. Mogul, "Registration
Procedures for Message Header Fields", BCP 90, RFC 3864, Procedures for Message Header Fields", BCP 90, RFC 3864,
DOI 10.17487/RFC3864, September 2004, DOI 10.17487/RFC3864, September 2004,
<https://www.rfc-editor.org/info/rfc3864>. <https://www.rfc-editor.org/info/rfc3864>.
skipping to change at page 21, line 29 skipping to change at page 21, line 45
available-values to preferred-available (preserving their available-values to preferred-available (preserving their
order). order).
4. If preferred-available is empty, append the first member of 4. If preferred-available is empty, append the first member of
available-values to preferred-available. This makes the first available-values to preferred-available. This makes the first
available-value the default when none of the client's preferences available-value the default when none of the client's preferences
are available. are available.
5. Return preferred-available. 5. Return preferred-available.
A.4. Cookie
This section defines variant handling for the Cookie request header
([RFC6265]).
This syntax of an available-value for Cookie is:
cookie-available-value = cookie-name
To perform content negotiation for Cookie given a request-value and
available-values:
1. Let cookies-available be an empty list.
2. For each available-value of available-values:
1. Parse request-value as a Cookie header field [RFC6265] and
let request-cookie-value be the cookie-value corresponding to
a cookie with a cookie-name that matches available-value. If
no match is found, continue to the next available-value.
2. append request-cookie-value to cookies-available.
3. Return cookies-available.
A simple example is allowing a page designed for users that aren't
logged in (denoted by the "logged_in" cookie-name) to be cached:
Variants: Cookie=(logged_in)
Variant-Key: (0)
Here, a cache that implements Variants will only use this response to
satisfy requests with "Cookie: logged_in=0".
Or, consider this example:
Variants: Cookie=(user_priority)
Variant-Key: (silver), ("bronze")
Here, the "user_priority" cookie-name allows requests from "gold"
users to be separated from "silver" and "bronze" ones; this response
is only served to the latter two.
It is possible to target a response to a single user; for example:
Variants: Cookie=(user_id)
Variant-Key: (some_person)
Here, only the "some_person" "user_id" will have this response served
to them again.
Note that if more than one cookie-name serves as a cache key, they'll
need to be listed in separate Variants members, like this:
Variants: Cookie=(user_priority), Cookie=(user_region)
Variant-Key: (gold europe)
Acknowledgements Acknowledgements
This protocol is conceptually similar to, but simpler than, This protocol is conceptually similar to, but simpler than,
Transparent Content Negotiation [RFC2295]. Thanks to its authors for Transparent Content Negotiation [RFC2295]. Thanks to its authors for
their inspiration. their inspiration.
It is also a generalisation of a Fastly VCL feature designed by It is also a generalisation of a Fastly VCL feature designed by
Rogier 'DocWilco' Mulhuijzen. Rogier 'DocWilco' Mulhuijzen.
Thanks to Hooman Beheshti, Ilya Grigorik, Leif Hedstrom, and Jeffrey Thanks to Hooman Beheshti, Ilya Grigorik, Leif Hedstrom, and Jeffrey
 End of changes. 52 change blocks. 
106 lines changed or deleted 174 lines changed or added

This html diff was produced by rfcdiff 1.44jr. The latest version is available from http://tools.ietf.org/tools/rfcdiff/