| < draft-ietf-httpbis-variants-04.txt | draft-ietf-httpbis-variants-05.txt > | |||
|---|---|---|---|---|
| HTTP M. Nottingham | HTTP M. Nottingham | |||
| Internet-Draft Fastly | Internet-Draft Fastly | |||
| Updates: 7234 (if approved) October 22, 2018 | Updates: 7234 (if approved) March 25, 2019 | |||
| Intended status: Standards Track | Intended status: Standards Track | |||
| Expires: April 25, 2019 | Expires: September 26, 2019 | |||
| HTTP Representation Variants | HTTP Representation Variants | |||
| draft-ietf-httpbis-variants-04 | draft-ietf-httpbis-variants-05 | |||
| 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 April 25, 2019. | This Internet-Draft will expire on September 26, 2019. | |||
| Copyright Notice | Copyright Notice | |||
| Copyright (c) 2018 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 . . . . . . . . . . . . . . . . . 4 | |||
| 2. The "Variants" HTTP Header Field . . . . . . . . . . . . . . 5 | 2. The "Variants" HTTP Header Field . . . . . . . . . . . . . . 5 | |||
| 2.1. Relationship to Vary . . . . . . . . . . . . . . . . . . 6 | 2.1. Relationship to Vary . . . . . . . . . . . . . . . . . . 7 | |||
| 3. The "Variant-Key" HTTP Header Field . . . . . . . . . . . . . 7 | 3. The "Variant-Key" HTTP Header Field . . . . . . . . . . . . . 7 | |||
| 3.1. Generating a Variant-Key List . . . . . . . . . . . . . . 7 | 4. Cache Behaviour . . . . . . . . . . . . . . . . . . . . . . . 9 | |||
| 4. Cache Behaviour . . . . . . . . . . . . . . . . . . . . . . . 8 | 4.1. Compute Possible Keys . . . . . . . . . . . . . . . . . . 10 | |||
| 4.1. Compute Possible Keys . . . . . . . . . . . . . . . . . . 9 | 4.2. Check Vary . . . . . . . . . . . . . . . . . . . . . . . 11 | |||
| 4.2. Check Vary . . . . . . . . . . . . . . . . . . . . . . . 10 | ||||
| 4.3. Example of Cache Behaviour . . . . . . . . . . . . . . . 11 | 4.3. Example of Cache Behaviour . . . . . . . . . . . . . . . 11 | |||
| 5. Origin Server Behaviour . . . . . . . . . . . . . . . . . . . 12 | 4.3.1. A Variant Missing From the Cache . . . . . . . . . . 12 | |||
| 5.1. Examples . . . . . . . . . . . . . . . . . . . . . . . . 12 | 4.3.2. Variants That Don't Overlap the Client's Request . . 13 | |||
| 5.1.1. Single Variant . . . . . . . . . . . . . . . . . . . 12 | 5. Origin Server Behaviour . . . . . . . . . . . . . . . . . . . 13 | |||
| 5.1.2. Multiple Variants . . . . . . . . . . . . . . . . . . 13 | 5.1. Examples . . . . . . . . . . . . . . . . . . . . . . . . 14 | |||
| 5.1.3. Partial Coverage . . . . . . . . . . . . . . . . . . 14 | 5.1.1. Single Variant . . . . . . . . . . . . . . . . . . . 14 | |||
| 6. Defining Content Negotiation Using Variants . . . . . . . . . 14 | 5.1.2. Multiple Variants . . . . . . . . . . . . . . . . . . 15 | |||
| 7. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 15 | 5.1.3. Partial Coverage . . . . . . . . . . . . . . . . . . 15 | |||
| 8. Security Considerations . . . . . . . . . . . . . . . . . . . 15 | 6. Defining Content Negotiation Using Variants . . . . . . . . . 16 | |||
| 9. References . . . . . . . . . . . . . . . . . . . . . . . . . 16 | 7. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 16 | |||
| 9.1. Normative References . . . . . . . . . . . . . . . . . . 16 | 8. Security Considerations . . . . . . . . . . . . . . . . . . . 17 | |||
| 9.2. Informative References . . . . . . . . . . . . . . . . . 16 | 9. References . . . . . . . . . . . . . . . . . . . . . . . . . 17 | |||
| 9.3. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 17 | 9.1. Normative References . . . . . . . . . . . . . . . . . . 17 | |||
| Appendix A. Variants for Existing Content Negotiation Mechanisms 17 | 9.2. Informative References . . . . . . . . . . . . . . . . . 18 | |||
| A.1. Accept . . . . . . . . . . . . . . . . . . . . . . . . . 17 | 9.3. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 18 | |||
| A.2. Accept-Encoding . . . . . . . . . . . . . . . . . . . . . 18 | Appendix A. Variants for Existing Content Negotiation Mechanisms 19 | |||
| A.3. Accept-Language . . . . . . . . . . . . . . . . . . . . . 19 | A.1. Accept . . . . . . . . . . . . . . . . . . . . . . . . . 19 | |||
| Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . 19 | A.2. Accept-Encoding . . . . . . . . . . . . . . . . . . . . . 20 | |||
| Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 20 | A.3. Accept-Language . . . . . . . . . . . . . . . . . . . . . 20 | |||
| Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . 21 | ||||
| Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 21 | ||||
| 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 | |||
| skipping to change at page 5, line 6 ¶ | skipping to change at page 5, line 6 ¶ | |||
| 1.1. Notational Conventions | 1.1. Notational Conventions | |||
| 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] with a list extension, defined in Section 7 of | notation of [RFC5234] but relies on Structured Headers from | |||
| [RFC7230], that allows for compact definition of comma-separated | [I-D.ietf-httpbis-header-structure] for parsing. | |||
| lists using a '#' operator (similar to how the '*' operator indicates | ||||
| repetition). | ||||
| Additionally, it uses the "field-name", "OWS" and "token" rules from | Additionally, it uses the "field-name" rule from [RFC7230], and | |||
| [RFC7230], and "type", "subtype", "content-coding" and "language- | "type", "subtype", "content-coding" and "language-range" from | |||
| range" from [RFC7231]. | [RFC7231]. | |||
| 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 the values that are available for each. | |||
| Variants = 1#variant-item | Variants is a Structured Header [I-D.ietf-httpbis-header-structure]. | |||
| variant-item = field-name *( OWS ";" OWS available-value ) | Its value MUST be a list-of-lists (Section 3.3 of | |||
| available-value = token | [I-D.ietf-httpbis-header-structure]) whose members are strings | |||
| / "/" / "?" / "\" / "[" / "]" | (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: | |||
| Each "variant-item" indicates a request header field that carries a | Variants = sh-list-of-lists | |||
| value that clients might proactively negotiate for; each parameter on | ||||
| it indicates a value for which there is an available representation | If Structured Header parsing fails or a list-member has the wrong | |||
| on the origin server. | type, the client MUST treat the representation as having no Variants | |||
| header field. | ||||
| The Variants header field represents an ordered list of "variant- | ||||
| axes", each of which consists of a request header "field-name" string | ||||
| and a list of "available-value" strings. Each inner-list in the | ||||
| 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- | ||||
| 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: | |||
| skipping to change at page 6, line 4 ¶ | skipping to change at page 6, line 15 ¶ | |||
| 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 HTTP header fields that use the "#" list rule (see | that, as with all Structured Header lists, they might occur in the | |||
| [RFC7230], Section 7), they might occur in the same header field or | same header field or separately, like this: | |||
| 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 after the field-name is significant, | |||
| as it might be used by the header's algorithm for selecting a | as it might be used by the header's algorithm for selecting a | |||
| response (in this example, the first language is the default; see | response (in this example, 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 | |||
| skipping to change at page 6, line 33 ¶ | skipping to change at page 6, line 44 ¶ | |||
| 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 | |||
| processing. | processing. | |||
| Likewise, servers MUST send the Variant-Key response header field | Likewise, servers MUST send the Variant-Key response header field | |||
| when sending Variants, since its absence means that the stored | when sending Variants, since its absence means that the stored | |||
| response will not be reused when this specification is implemented. | response will not be reused when this specification is implemented. | |||
| _RFC EDITOR: Please remove the next paragraph before publication._ | ||||
| Implementations of drafts of this specification MUST implement an | ||||
| HTTP header field named "Variants-##" instead of the "Variants" | ||||
| header field specified by the final RFC, with "##" replaced by the | ||||
| draft number being implemented. For example, implementations of | ||||
| draft-ietf-httpbis-variants-05 would implement "Variants-05". | ||||
| 2.1. Relationship to Vary | 2.1. Relationship to Vary | |||
| This specification updates [RFC7234] to allow caches that implement | This specification updates [RFC7234] to allow caches that implement | |||
| it to ignore request header fields in the Vary header for the | it to ignore request header fields in the Vary header for the | |||
| purposes of secondary cache key calculation ([RFC7234], Section 4.1) | purposes of secondary cache key calculation ([RFC7234], Section 4.1) | |||
| when their semantics are implemented as per this specification and | when their semantics are implemented as per this specification and | |||
| their corresponding response header field is listed in Variants. | their corresponding response header field is listed in Variants. | |||
| If any member of the Vary header does not have a corresponding | If any member of the Vary header does not have a corresponding | |||
| variant that is understood by the implementation, it is still subject | variant that is understood by the implementation, it is still subject | |||
| skipping to change at page 7, line 7 ¶ | skipping to change at page 7, line 27 ¶ | |||
| 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 is used to indicate the | The Variant-Key HTTP response header field identifies a set of | |||
| values from the Variants header field that identify the | variants provided by the representation it occurs within. A variant | |||
| representation it occurs within. | is identified by a selection of one available-value from each | |||
| variant-axis from the Variants header field. | ||||
| Variant-Key = 1#available-values | Variant-Key is a Structured Header | |||
| available-values = available-value *( ";" available-value ) | [I-D.ietf-httpbis-header-structure]. Its value MUST be a list-of- | |||
| lists (Section 3.3 of [I-D.ietf-httpbis-header-structure]) whose | ||||
| members are strings (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: | ||||
| Each member of the list contains a set of selected available-value(s) | Variant-Key = sh-list-of-lists | |||
| that identify this representation, in the same order as the variants | ||||
| listed in the Variants header field. | ||||
| Therefore, each member of Variant-Key MUST be the same length (in | If Structured Header parsing fails or a list-member has the wrong | |||
| semicolon-separated members) as Variants, and each member's | type, the client MUST treat the representation as having no Variant- | |||
| available-values MUST correspond in position to their companions in | Key header field. | |||
| Variants. | ||||
| Each inner-list MUST have the same number of list-members as there | ||||
| are variant-axes in the representation's Variants header field. If | ||||
| not, the client MUST treat the representation as having no Variant- | ||||
| Key header field. | ||||
| Each list-member is treated as identifying an available-value for the | ||||
| corresponding variant-axis' field-name. 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. These | ||||
| 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 indicate the variant-key for the response it occurs | present MUST correspond to the request that caused that response to | |||
| within. | be generated. | |||
| 3.1. Generating a Variant-Key List | ||||
| This algorithm generates a list of normalised strings from Variant- | ||||
| Key, suitable for comparison with values generated by Section 4. | ||||
| Given stored-headers (a set of headers from a stored response), a | ||||
| normalised list of variant-keys for that message can be generated by | ||||
| following this algorithm: | ||||
| 1. Let variant-keys be an empty list. | Parsing is strict. For example: | |||
| 2. Let variant-key-header be a string, the result of selecting all | Variants: Accept-Encoding;gzip;br, Accept-Language;en ;fr | |||
| field-values of stored-headers whose field-name is "Variant-Key" | Variant-Key: gzip;fr, identity;fr, br;fr;oops | |||
| and joining them with a comma (","). | ||||
| 3. Let value-list be the result of splitting variant-key-header on | is treated as if the Variant-Key header were completely absent, which | |||
| commas (","). | will tend to disable caching for the representation that contains it. | |||
| 4. For each value in value-list: | Note that in | |||
| 1. Remove all whitespace from value. | Variant-Key: gzip ;fr | |||
| Variant-Key: "gzip ";fr | ||||
| 2. Append value to variant-keys. | The whitespace after "gzip" in the first header field value is | |||
| excluded by the token parsing algorithm, but the whitespace in the | ||||
| second header field value is included by the string parsing | ||||
| algorithm. This will likely cause the second header field value to | ||||
| fail to match client requests. | ||||
| 5. Return variant-keys. | _RFC EDITOR: Please remove the next paragraph before publication._ | |||
| Implementations of drafts of this specification MUST implement an | ||||
| HTTP header field named "Variant-Key-##" instead of the "Variant-Key" | ||||
| header field specified by the final RFC, with "##" replaced by the | ||||
| draft number being implemented. For example, implementations of | ||||
| 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-name 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 lists of field | |||
| values), and stored-responses (a list of stored responses suitable | values), and stored-responses (a list of stored responses suitable | |||
| for reuse as defined in Section 4 of [RFC7234], excepting the | for reuse as defined in Section 4 of [RFC7234], excepting the | |||
| requirement to calculate a secondary cache key): | 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): | Section 4.2) has one or more "Variants" header field(s) that | |||
| successfully parse according to Section 2: | ||||
| 1. Select one member of stored-responses and let variants-header | ||||
| be its "Variants" header field-value(s). This SHOULD be the | ||||
| most recent response, but MAY be from an older one as long as | ||||
| it is still fresh. | ||||
| 2. For each variant in variants-header, parsed according to the | 1. Select one member of stored-responses with a "Variants" | |||
| ABNF: | header field-value(s) that successfully parses according to | |||
| Section 2 and let variants-header be this parsed value. This | ||||
| SHOULD be the most recent response, but MAY be from an older | ||||
| one as long as it is still fresh. | ||||
| 1. If variant's field-name corresponds to the request header | 2. For each variant-axis in variants-header: | |||
| field identified by a content negotiation mechanism that | ||||
| the implementation supports: | ||||
| 1. Let request-value be the field-value(s) associated | 1. If variant-axis' field-name corresponds to the request | |||
| with field-name in incoming-request. | header field identified by a content negotiation | |||
| mechanism that the implementation supports: | ||||
| 2. Let available-values be a list containing all | 1. Let request-value be the field-value associated with | |||
| available-value for variant. | field-name in incoming-request (after being combined | |||
| as allowed by Section 3.2.2 of [RFC7230]), or null if | ||||
| field-name is not in incoming-request. | ||||
| 3. 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 available-values. | mechanism with request-value and variant-axis' | |||
| available-values. | ||||
| 4. 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-item | member of the top-level list corresponding to a variant-axis | |||
| in the Variants header field-value, containing zero or more | in the Variants header field-value, containing zero or more | |||
| items indicating available-values that are acceptable to the | items indicating available-values that are acceptable to the | |||
| client, in order of preference, greatest to least. | client, in order of preference, greatest to least. | |||
| 5. Return result of running Compute Possible Keys (Section 4.1) on | 5. Return result of running Compute Possible Keys (Section 4.1) on | |||
| sorted-variants, an empty string and an empty list. | sorted-variants, an empty list and an empty list. | |||
| This returns a list of strings suitable for comparing to normalised | This returns a list of lists of strings suitable for comparing to the | |||
| Variant-Keys (Section 3.1) that represent possible responses on the | parsed Variant-Keys (Section 3) that represent possible responses on | |||
| server that can be used to satisfy the request, in preference order, | the server that can be used to satisfy the request, in preference | |||
| provided that their secondary cache key (after removing the headers | order, provided that their secondary cache key (after removing the | |||
| covered by Variants) matches. Section 4.2 illustrates one way to do | headers covered by Variants) matches. Section 4.2 illustrates one | |||
| this. | way to do this. | |||
| 4.1. Compute Possible Keys | 4.1. Compute Possible Keys | |||
| This algorithm computes the cross-product of the elements of key- | This algorithm computes the cross-product of the elements of key- | |||
| facets. | facets. | |||
| Given key-facets (a list of lists), and key-stub (a string | Given key-facets (a list of lists of strings), and key-stub (a list | |||
| representing a partial key), and possible-keys (a list): | of strings representing a partial key), and possible-keys (a list of | |||
| lists of strings): | ||||
| 1. Let values be the first member of key-facets. | 1. Let values be the first member of key-facets. | |||
| 2. For each value in values: | 2. Let remaining-facets be a copy of all of the members of key- | |||
| facets except the first. | ||||
| 1. If key-stub is an empty string, let this-key be a copy of | ||||
| value. | ||||
| 2. Otherwise: | ||||
| 1. Let this-key be a copy of key-stub. | ||||
| 2. Append a semicolon (";") to this-key. | 3. For each value in values: | |||
| 3. Append value to this-key. | 1. Let this-key be a copy of key-stub. | |||
| 3. Let remaining-facets be a copy of all of the members of key- | 2. Append value to this-key. | |||
| facets except the first. | ||||
| 4. If remaining-facets is empty, append this-key to possible- | 3. If remaining-facets is empty, append this-key to possible- | |||
| keys. | keys. | |||
| 5. Otherwise, run Compute Possible Keys on remaining-facets, | 4. Otherwise, run Compute Possible Keys on remaining-facets, | |||
| this-key and possible-keys. | this-key and possible-keys. | |||
| 3. 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 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 | |||
| skipping to change at page 11, line 31 ¶ | skipping to change at page 12, line 10 ¶ | |||
| 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 | |||
| ["gzip", "identity"] // prefers gzip encoding, will accept identity | ["gzip", "identity"] // prefers gzip encoding, will accept identity | |||
| ] | ] | |||
| Which means that the sorted-keys would be: | Which means that the result of the Cache Behaviour algorithm would | |||
| be: | ||||
| [ | [ | |||
| '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 | ||||
| If the selected variants-header was: | ||||
| Variants: Accept-Language;en;fr;de | ||||
| And a request comes in with the following headers: | ||||
| Accept-Language: de;q=1.0, es;q=0.8 | ||||
| Then sorted-variants in Cache Behaviour is: | ||||
| [ | ||||
| ["de"] // prefers German; will not accept English | ||||
| ] | ||||
| If the cache contains responses with the following Variant-Keys: | ||||
| Variant-Key: fr | ||||
| Variant-Key: en | ||||
| Then the cache needs to forward the request to the origin server, | ||||
| since Variants indicates that "de" is available, and that is | ||||
| acceptable to the client. | ||||
| 4.3.2. Variants That Don't Overlap the Client's Request | ||||
| If the selected variants-header was: | ||||
| Variants: Accept-Language;en;fr;de | ||||
| And a request comes in with the following headers: | ||||
| Accept-Language: es;q=1.0, ja;q=0.8 | ||||
| Then sorted-variants in Cache Behaviour are: | ||||
| [ | ||||
| ["en"] | ||||
| ] | ||||
| This allows the cache to return a "Variant-Key: en" response even | ||||
| though it's not in the set the client prefers. | ||||
| 5. Origin Server Behaviour | 5. Origin Server Behaviour | |||
| Origin servers that wish to take advantage of Variants will need to | Origin servers that wish to take advantage of Variants will need to | |||
| generate both the Variants (Section 2) and Variant-Key (Section 3) | generate both the Variants (Section 2) and Variant-Key (Section 3) | |||
| header fields in all cacheable responses for a given resource. If | header fields in all cacheable responses for a given resource. If | |||
| either is omitted and the response is stored, it will have the effect | either is omitted and the response is stored, it will have the effect | |||
| of disabling caching for that resource until it is no longer stored | of disabling caching for that resource until it is no longer stored | |||
| (e.g., it expires, or is evicted). | (e.g., it expires, or is evicted). | |||
| Likewise, origin servers will need to assure that the members of both | Likewise, origin servers will need to assure that the members of both | |||
| skipping to change at page 14, line 48 ¶ | skipping to change at page 16, line 33 ¶ | |||
| o MUST define a request header field that advertises the clients | o MUST define a request header field that advertises the clients | |||
| preferences or capabilities, whose field-name SHOULD begin with | preferences or capabilities, whose field-name SHOULD begin with | |||
| "Accept-". | "Accept-". | |||
| o MUST define the syntax of an available-value that will occur in | o MUST define the syntax of an available-value that will occur in | |||
| Variants and Variant-Key. | Variants and Variant-Key. | |||
| o MUST define an algorithm for selecting a result. It MUST return a | o MUST define an algorithm for selecting a result. It MUST return a | |||
| list of available-values that are suitable for the request, in | list of available-values that are suitable for the request, in | |||
| order of preference, given the value of the request header | order of preference, given the value of the request header | |||
| nominated above and an available-values list from the Variants | nominated above (or null if the request header is absent) and an | |||
| header. If the result is an empty list, it implies that the cache | available-values list from the Variants header. If the result is | |||
| cannot satisfy the request. | an empty list, it implies that the cache cannot satisfy the | |||
| request. | ||||
| Appendix A fulfils these requirements for some existing proactive | Appendix A fulfils these requirements for some existing proactive | |||
| content negotiation mechanisms in HTTP. | content negotiation mechanisms in HTTP. | |||
| 7. IANA Considerations | 7. IANA Considerations | |||
| This specification registers the following entry in the Permanent | This specification registers the following entry in the Permanent | |||
| Message Header Field Names registry established by [RFC3864]: | Message Header Field Names registry established by [RFC3864]: | |||
| o Header field name: Variants | o Header field name: Variants | |||
| skipping to change at page 16, line 9 ¶ | skipping to change at page 17, line 39 ¶ | |||
| header by its nature will leak them. | header by its nature will leak them. | |||
| 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] | ||||
| Nottingham, M. and P. Kamp, "Structured Headers for HTTP", | ||||
| draft-ietf-httpbis-header-structure-09 (work in progress), | ||||
| December 2018. | ||||
| [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 | |||
| skipping to change at page 17, line 40 ¶ | skipping to change at page 19, line 25 ¶ | |||
| The syntax of an available-value for Accept is: | The syntax of an available-value for Accept is: | |||
| accept-available-value = type "/" subtype | accept-available-value = type "/" subtype | |||
| To perform content negotiation for Accept given a request-value and | To perform content negotiation for Accept given a request-value and | |||
| available-values: | available-values: | |||
| 1. Let preferred-available be an empty list. | 1. Let preferred-available be an empty list. | |||
| 2. Let preferred-types be a list of the types in the request-value, | 2. Let preferred-types be a list of the types in the request-value | |||
| ordered by their weight, highest to lowest, as per Section 5.3.2 | (or the empty list if request-value is null), ordered by their | |||
| of [RFC7231] (omitting any coding with a weight of 0). If | weight, highest to lowest, as per Section 5.3.2 of [RFC7231] | |||
| "Accept" is not present or empty, preferred-types will be empty. | (omitting any coding with a weight of 0). If a type lacks an | |||
| If a type lacks an explicit weight, an implementation MAY assign | explicit weight, an implementation MAY assign one. | |||
| one. | ||||
| 3. If the first member of available-values is not a member of | ||||
| preferred-types, append it to preferred-types (thus making it the | ||||
| default). | ||||
| 4. For each preferred-type in preferred-types: | 3. For each preferred-type in preferred-types: | |||
| 1. If any member of available-values matches preferred-type, | 1. If any member of available-values matches preferred-type, | |||
| using the media-range matching mechanism specified in | using the media-range matching mechanism specified in | |||
| Section 5.3.2 of [RFC7231] (which is case-insensitive), | Section 5.3.2 of [RFC7231] (which is case-insensitive), | |||
| append those members of available-values to preferred- | append those members of available-values to preferred- | |||
| available (preserving the precedence order implied by the | available (preserving the precedence order implied by the | |||
| media ranges' specificity). | media ranges' specificity). | |||
| 4. If preferred-available is empty, append the first member of | ||||
| available-values to preferred-available. This makes the first | ||||
| available-value the default when none of the client's preferences | ||||
| are available. | ||||
| 5. Return preferred-available. | 5. Return preferred-available. | |||
| Note that this algorithm explicitly ignores extension parameters on | Note that this algorithm explicitly ignores extension parameters on | |||
| media types (e.g., "charset"). | media types (e.g., "charset"). | |||
| A.2. Accept-Encoding | A.2. Accept-Encoding | |||
| This section defines variant handling for the Accept-Encoding request | This section defines variant handling for the Accept-Encoding request | |||
| header (section 5.3.4 of [RFC7231]). | header (section 5.3.4 of [RFC7231]). | |||
| The syntax of an available-value for Accept-Encoding is: | The syntax of an available-value for Accept-Encoding is: | |||
| accept-encoding-available-value = content-coding / "identity" | accept-encoding-available-value = content-coding / "identity" | |||
| To perform content negotiation for Accept-Encoding given a request- | To perform content negotiation for Accept-Encoding given a request- | |||
| value and available-values: | value and available-values: | |||
| 1. Let preferred-available be an empty list. | 1. Let preferred-available be an empty list. | |||
| 2. Let preferred-codings be a list of the codings in the request- | 2. Let preferred-codings be a list of the codings in the request- | |||
| value, ordered by their weight, highest to lowest, as per | value (or the empty list if request-value is null), ordered by | |||
| Section 5.3.1 of [RFC7231] (omitting any coding with a weight of | their weight, highest to lowest, as per Section 5.3.1 of | |||
| 0). If "Accept-Encoding" is not present or empty, preferred- | [RFC7231] (omitting any coding with a weight of 0). If a coding | |||
| codings will be empty. If a coding lacks an explicit weight, an | lacks an explicit weight, an implementation MAY assign one. | |||
| implementation MAY assign one. | ||||
| 3. If "identity" is not a member of preferred-codings, append | 3. If "identity" is not a member of preferred-codings, append | |||
| "identity". | "identity". | |||
| 4. Append "identity" to available-values. | 4. Append "identity" to available-values. | |||
| 5. For each preferred-coding in preferred-codings: | 5. For each preferred-coding in preferred-codings: | |||
| 1. If there is a case-insensitive, character-for-character match | 1. If there is a case-insensitive, character-for-character match | |||
| for preferred-coding in available-values, append that member | for preferred-coding in available-values, append that member | |||
| skipping to change at page 19, line 24 ¶ | skipping to change at page 21, line 8 ¶ | |||
| The syntax of an available-value for Accept-Language is: | The syntax of an available-value for Accept-Language is: | |||
| accept-encoding-available-value = language-range | accept-encoding-available-value = language-range | |||
| To perform content negotiation for Accept-Language given a request- | To perform content negotiation for Accept-Language given a request- | |||
| value and available-values: | value and available-values: | |||
| 1. Let preferred-available be an empty list. | 1. Let preferred-available be an empty list. | |||
| 2. Let preferred-langs be a list of the language-ranges in the | 2. Let preferred-langs be a list of the language-ranges in the | |||
| request-value, ordered by their weight, highest to lowest, as per | request-value (or the empty list if request-value is null), | |||
| Section 5.3.1 of [RFC7231] (omitting any language-range with a | ordered by their weight, highest to lowest, as per Section 5.3.1 | |||
| weight of 0). If a language-range lacks a weight, an | of [RFC7231] (omitting any language-range with a weight of 0). | |||
| implementation MAY assign one. | If a language-range lacks a weight, an implementation MAY assign | |||
| one. | ||||
| 3. If the first member of available-values is not a member of | ||||
| preferred-langs, append it to preferred-langs (thus making it the | ||||
| default). | ||||
| 4. For each preferred-lang in preferred-langs: | 3. For each preferred-lang in preferred-langs: | |||
| 1. If any member of available-values matches preferred-lang, | 1. If any member of available-values matches preferred-lang, | |||
| using either the Basic or Extended Filtering scheme defined | using either the Basic or Extended Filtering scheme defined | |||
| in Section 3.3 of [RFC4647], append those members of | in Section 3.3 of [RFC4647], append those members of | |||
| 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 | ||||
| available-values to preferred-available. This makes the first | ||||
| available-value the default when none of the client's preferences | ||||
| are available. | ||||
| 5. Return preferred-available. | 5. Return preferred-available. | |||
| 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. | |||
| End of changes. 62 change blocks. | ||||
| 160 lines changed or deleted | 244 lines changed or added | |||
This html diff was produced by rfcdiff 1.48. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ | ||||