idnits 2.17.1 draft-ietf-httpbis-variants-03.txt: Checking boilerplate required by RFC 5378 and the IETF Trust (see https://trustee.ietf.org/license-info): ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/1id-guidelines.txt: ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/checklist : ---------------------------------------------------------------------------- ** The abstract seems to contain references ([2], [3], [4], [1]), which it shouldn't. Please replace those with straight textual mentions of the documents in question. -- The draft header indicates that this document updates RFC7234, but the abstract doesn't seem to mention this, which it should. Miscellaneous warnings: ---------------------------------------------------------------------------- == The copyright year in the IETF Trust and authors Copyright Line does not match the current year (Using the creation date from RFC7234, updated by this document, for RFC5378 checks: 2007-12-21) -- The document seems to lack a disclaimer for pre-RFC5378 work, but may have content which was first submitted before 10 November 2008. If you have contacted all the original authors and they are all willing to grant the BCP78 rights to the IETF Trust, then this is fine, and you can ignore this comment. If not, you may need to add the pre-RFC5378 disclaimer. (See the Legal Provisions document at https://trustee.ietf.org/license-info for more information.) -- The document date (July 1, 2018) is 2119 days in the past. Is this intentional? Checking references for intended status: Proposed Standard ---------------------------------------------------------------------------- (See RFCs 3967 and 4897 for information about using normative references to lower-maturity documents in RFCs) -- Looks like a reference, but probably isn't: '1' on line 759 -- Looks like a reference, but probably isn't: '2' on line 761 -- Looks like a reference, but probably isn't: '3' on line 763 -- Looks like a reference, but probably isn't: '4' on line 765 ** Obsolete normative reference: RFC 7230 (Obsoleted by RFC 9110, RFC 9112) ** Obsolete normative reference: RFC 7231 (Obsoleted by RFC 9110) ** Obsolete normative reference: RFC 7234 (Obsoleted by RFC 9111) == Outdated reference: A later version (-15) exists of draft-ietf-httpbis-client-hints-05 Summary: 4 errors (**), 0 flaws (~~), 2 warnings (==), 7 comments (--). Run idnits with the --verbose option for more detailed information about the items above. -------------------------------------------------------------------------------- 2 HTTP M. Nottingham 3 Internet-Draft Fastly 4 Updates: 7234 (if approved) July 1, 2018 5 Intended status: Standards Track 6 Expires: January 2, 2019 8 HTTP Representation Variants 9 draft-ietf-httpbis-variants-03 11 Abstract 13 This specification introduces an alternative way to communicate a 14 secondary cache key for a HTTP resource, using the HTTP "Variants" 15 and "Variant-Key" response header fields. Its aim is to make HTTP 16 proactive content negotiation more cache-friendly. 18 Note to Readers 20 _RFC EDITOR: please remove this section before publication_ 22 Discussion of this draft takes place on the HTTP working group 23 mailing list (ietf-http-wg@w3.org), which is archived at 24 https://lists.w3.org/Archives/Public/ietf-http-wg/ [1]. 26 Working Group information can be found at https://httpwg.github.io/ 27 [2]; source code and issues list for this draft can be found at 28 https://github.com/httpwg/http-extensions/labels/variants [3]. 30 There is a prototype implementation of the algorithms herein at 31 https://github.com/mnot/variants-toy [4]. 33 Status of This Memo 35 This Internet-Draft is submitted in full conformance with the 36 provisions of BCP 78 and BCP 79. 38 Internet-Drafts are working documents of the Internet Engineering 39 Task Force (IETF). Note that other groups may also distribute 40 working documents as Internet-Drafts. The list of current Internet- 41 Drafts is at https://datatracker.ietf.org/drafts/current/. 43 Internet-Drafts are draft documents valid for a maximum of six months 44 and may be updated, replaced, or obsoleted by other documents at any 45 time. It is inappropriate to use Internet-Drafts as reference 46 material or to cite them other than as "work in progress." 48 This Internet-Draft will expire on January 2, 2019. 50 Copyright Notice 52 Copyright (c) 2018 IETF Trust and the persons identified as the 53 document authors. All rights reserved. 55 This document is subject to BCP 78 and the IETF Trust's Legal 56 Provisions Relating to IETF Documents 57 (https://trustee.ietf.org/license-info) in effect on the date of 58 publication of this document. Please review these documents 59 carefully, as they describe your rights and restrictions with respect 60 to this document. Code Components extracted from this document must 61 include Simplified BSD License text as described in Section 4.e of 62 the Trust Legal Provisions and are provided without warranty as 63 described in the Simplified BSD License. 65 Table of Contents 67 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 68 1.1. Notational Conventions . . . . . . . . . . . . . . . . . 4 69 2. The "Variants" HTTP Header Field . . . . . . . . . . . . . . 5 70 2.1. Relationship to Vary . . . . . . . . . . . . . . . . . . 6 71 3. The "Variant-Key" HTTP Header Field . . . . . . . . . . . . . 7 72 3.1. Generating a Variant-Key List . . . . . . . . . . . . . . 7 73 4. Cache Behaviour . . . . . . . . . . . . . . . . . . . . . . . 8 74 4.1. Compute Possible Keys . . . . . . . . . . . . . . . . . . 9 75 4.2. Check Vary . . . . . . . . . . . . . . . . . . . . . . . 10 76 4.3. Example of Cache Behaviour . . . . . . . . . . . . . . . 11 77 5. Origin Server Behaviour . . . . . . . . . . . . . . . . . . . 12 78 5.1. Examples . . . . . . . . . . . . . . . . . . . . . . . . 12 79 5.1.1. Single Variant . . . . . . . . . . . . . . . . . . . 12 80 5.1.2. Multiple Variants . . . . . . . . . . . . . . . . . . 13 81 5.1.3. Partial Coverage . . . . . . . . . . . . . . . . . . 14 82 6. Defining Content Negotiation Using Variants . . . . . . . . . 14 83 7. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 15 84 8. Security Considerations . . . . . . . . . . . . . . . . . . . 15 85 9. References . . . . . . . . . . . . . . . . . . . . . . . . . 15 86 9.1. Normative References . . . . . . . . . . . . . . . . . . 16 87 9.2. Informative References . . . . . . . . . . . . . . . . . 16 88 9.3. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 17 89 Appendix A. Variants for Existing Content Negotiation Mechanisms 17 90 A.1. Accept . . . . . . . . . . . . . . . . . . . . . . . . . 17 91 A.2. Accept-Encoding . . . . . . . . . . . . . . . . . . . . . 18 92 A.3. Accept-Language . . . . . . . . . . . . . . . . . . . . . 19 93 Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . 19 94 Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 20 96 1. Introduction 98 HTTP proactive content negotiation ([RFC7231], Section 3.4.1) is 99 seeing renewed interest, both for existing request headers like 100 Accept-Language and for newer ones (for example, see 101 [I-D.ietf-httpbis-client-hints]). 103 Successfully reusing negotiated responses that have been stored in a 104 HTTP cache requires establishment of a secondary cache key 105 ([RFC7234], Section 4.1). Currently, the Vary header ([RFC7231], 106 Section 7.1.4) does this by nominating a set of request headers. 108 HTTP's caching model allows a certain amount of latitude in 109 normalising those request header field values, so as to increase the 110 chances of a cache hit while still respecting the semantics of that 111 header. However, normalisation is not formally defined, leading to 112 divergence in cache behaviours. 114 Even when the headers' semantics are understood, a cache does not 115 know enough about the possible alternative representations available 116 on the origin server to make an appropriate decision. 118 For example, if a cache has stored the following request/response 119 pair: 121 GET /foo HTTP/1.1 122 Host: www.example.com 123 Accept-Language: en;q=0.5, fr;q=1.0 125 HTTP/1.1 200 OK 126 Content-Type: text/html 127 Content-Language: en 128 Vary: Accept-Language 129 Transfer-Encoding: chunked 131 [French content] 133 Provided that the cache has full knowledge of the semantics of 134 Accept-Language and Content-Language, it will know that an English 135 representation is available and might be able to infer that a French 136 representation is not available. But, it does not know (for example) 137 whether a Japanese representation is available without making another 138 request, incurring possibly unnecessary latency. 140 This specification introduces the HTTP Variants response header field 141 (Section 2) to enumerate the available variant representations on the 142 origin server, to provide clients and caches with enough information 143 to properly satisfy requests - either by selecting a response from 144 cache or by forwarding the request towards the origin - by following 145 the algorithm defined in Section 4. 147 Its companion Variant-Key response header field (Section 3) indicates 148 the applicable key(s) that the response is associated with, so that 149 it can be reliably reused in the future. When this specification is 150 in use, the example above might become: 152 GET /foo HTTP/1.1 153 Host: www.example.com 154 Accept-Language: en;q=0.5, fr;q=1.0 156 HTTP/1.1 200 OK 157 Content-Type: text/html 158 Content-Language: en 159 Vary: Accept-Language 160 Variants: Accept-Language;de;en;jp 161 Variant-Key: en 162 Transfer-Encoding: chunked 164 [French content] 166 Proactive content negotiation mechanisms that wish to be used with 167 Variants need to define how to do so explicitly; see Section 6. As a 168 result, it is best suited for negotiation over request headers that 169 are well-understood. 171 Variants also works best when content negotiation takes place over a 172 constrained set of representations; since each variant needs to be 173 listed in the header field, it is ill-suited for open-ended sets of 174 representations. 176 Variants can be seen as a simpler version of the Alternates header 177 field introduced by [RFC2295]; unlike that mechanism, Variants does 178 not require specification of each combination of attributes, and does 179 not assume that each combination has a unique URL. 181 1.1. Notational Conventions 183 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", 184 "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and 185 "OPTIONAL" in this document are to be interpreted as described in BCP 186 14 [RFC2119] [RFC8174] when, and only when, they appear in all 187 capitals, as shown here. 189 This specification uses the Augmented Backus-Naur Form (ABNF) 190 notation of [RFC5234] with a list extension, defined in Section 7 of 191 [RFC7230], that allows for compact definition of comma-separated 192 lists using a '#' operator (similar to how the '*' operator indicates 193 repetition). 195 Additionally, it uses the "field-name", "OWS" and "token" rules from 196 [RFC7230], and "type", "subtype", "content-coding" and "language- 197 range" from [RFC7231]. 199 2. The "Variants" HTTP Header Field 201 The Variants HTTP response header field indicates what 202 representations are available for a given resource at the time that 203 the response is produced, by enumerating the request header fields 204 that it varies on, along with the values that are available for each. 206 Variants = 1#variant-item 207 variant-item = field-name *( OWS ";" OWS available-value ) 208 available-value = token 209 / "/" / "?" / "\" / "[" / "]" 210 / ":" / "@" / "(" / ")" 212 Each "variant-item" indicates a request header field that carries a 213 value that clients might proactively negotiate for; each parameter on 214 it indicates a value for which there is an available representation 215 on the origin server. 217 So, given this example header field: 219 Variants: Accept-Encoding;gzip 221 a recipient can infer that the only content-coding available for that 222 resource is "gzip" (along with the "identity" non-encoding; see 223 Appendix A.2). 225 Given: 227 Variants: accept-encoding 229 a recipient can infer that no content-codings (beyond identity) are 230 supported. Note that as always, field-name is case-insensitive. 232 A more complex example: 234 Variants: Accept-Encoding;gzip;br, Accept-Language;en ;fr 235 Here, recipients can infer that two content-codings in addition to 236 "identity" are available, as well as two content languages. Note 237 that, as with all HTTP header fields that use the "#" list rule (see 238 [RFC7230], Section 7), they might occur in the same header field or 239 separately, like this: 241 Variants: Accept-Encoding;gzip;brotli 242 Variants: Accept-Language;en ;fr 244 The ordering of available-values after the field-name is significant, 245 as it might be used by the header's algorithm for selecting a 246 response (in this example, the first language is the default; see 247 Appendix A.3). 249 The ordering of the request header fields themselves indicates 250 descending application of preferences; in the example above, a cache 251 that has all of the possible permutations stored will honour the 252 client's preferences for Accept-Encoding before honouring Accept- 253 Language. 255 Origin servers SHOULD consistently send Variant header fields on all 256 cacheable (as per [RFC7234], Section 3) responses for a resource, 257 since its absence will trigger caches to fall back to Vary 258 processing. 260 Likewise, servers MUST send the Variant-Key response header field 261 when sending Variants, since its absence means that the stored 262 response will not be reused when this specification is implemented. 264 2.1. Relationship to Vary 266 This specification updates [RFC7234] to allow caches that implement 267 it to ignore request header fields in the Vary header for the 268 purposes of secondary cache key calculation ([RFC7234], Section 4.1) 269 when their semantics are implemented as per this specification and 270 their corresponding response header field is listed in Variants. 272 If any member of the Vary header does not have a corresponding 273 variant that is understood by the implementation, it is still subject 274 to the requirements there. 276 See Section 5.1.3 for an example. 278 In practice, implementation of Vary varies considerably. As a 279 result, cache efficiency might drop considerably when Variants does 280 not contain all of the headers referenced by Vary, because some 281 implementations might choose to disable Variants processing when this 282 is the case. 284 3. The "Variant-Key" HTTP Header Field 286 The Variant-Key HTTP response header field is used to indicate the 287 values from the Variants header field that identify the 288 representation it occurs within. 290 Variant-Key = 1#available-values 291 available-values = available-value *( ";" available-value ) 293 Each member of the list contains the selected available-value(s), in 294 the same order as the variants listed in the Variants header field. 296 Therefore, Variant-Key MUST be the same length (in comma-separated 297 members) as Variants, and each member MUST correspond in position to 298 its companion in Variants. 300 For example: 302 Variants: Accept-Encoding;gzip;br, Accept-Language;en ;fr 303 Variant-Key: gzip, fr 305 This header pair indicates that the representation has a "gzip" 306 content-coding and "fr" content-language. 308 A more complex example involves listing multiple available-values in 309 a list member, to indicate that the response can be used to satisfy 310 requests with any of those values. For example: 312 Variants: Accept-Encoding;gzip;br, Accept-Language;en ;fr 313 Variant-Key: gzip;identity, fr 315 indicates that this response can be used for requests whose Accept- 316 Encoding algorithm selects "gzip" or "identity", as long as the 317 Accept-Language algorithm selects "fr" - perhaps because there is no 318 gzip-compressed French representation. 320 This highlights an important aspect of Variant-Key; it is only used 321 to indicate what request attributes are associated with the response 322 containing it; this is different from headers like Content-Encoding, 323 which indicate attributes of the response itself. 325 3.1. Generating a Variant-Key List 327 This algorithm generates a list of normalised strings from Variant- 328 Key, suitable for comparison with values generated by Section 4. 330 Given stored-headers (a set of headers from a stored response), a 331 normalised list of variant-keys for that message can be generated by 332 following this algorithm: 334 1. Let variant-keys be an empty list. 336 2. Let variant-key-header be a string, the result of selecting all 337 field-values of stored-headers whose field-name is "Variant-Key" 338 and joining them with a comma (","). 340 3. Let value-list be the result of splitting variant-key-header on 341 commas (","). 343 4. For each value in value-list: 345 1. Remove all whitespace from value. 347 2. Let items be the result of splitting value on ";". 349 3. append items to variant-keys. 351 5. Return the result of running Compute Possible Keys (Section 4.1) 352 on variant-keys, an empty string and an empty list. 354 4. Cache Behaviour 356 Caches that implement the Variants header field and the relevant 357 semantics of the field-name it contains can use that knowledge to 358 either select an appropriate stored representation, or forward the 359 request if no appropriate representation is stored. 361 They do so by running this algorithm (or its functional equivalent) 362 upon receiving a request: 364 Given incoming-request (a mapping of field-names to lists of field 365 values), and stored-responses (a list of stored responses suitable 366 for reuse as defined in Section 4 of [RFC7234], excepting the 367 requirement to calculate a secondary cache key): 369 1. If stored-responses is empty, return an empty list. 371 2. Order stored-responses by the "Date" header field, most recent to 372 least recent. 374 3. Let sorted-variants be an empty list. 376 4. If the freshest member of stored-responses (as per [RFC7234], 377 Section 4.2) has one or more "Variants" header field(s): 379 1. Select one member of stored-responses and let variants-header 380 be its "Variants" header field-value(s). This SHOULD be the 381 most recent response, but MAY be from an older one as long as 382 it is still fresh. 384 2. For each variant in variants-header, parsed according to the 385 ABNF: 387 1. If variant's field-name corresponds to the request header 388 field identified by a content negotiation mechanism that 389 the implementation supports: 391 1. Let request-value be the field-value(s) associated 392 with field-name in incoming-request. 394 2. Let available-values be a list containing all 395 available-value for variant. 397 3. Let sorted-values be the result of running the 398 algorithm defined by the content negotiation 399 mechanism with request-value and available-values. 401 4. Append sorted-values to sorted-variants. 403 At this point, sorted-variants will be a list of lists, each 404 member of the top-level list corresponding to a variant-item 405 in the Variants header field-value, containing zero or more 406 items indicating available-values that are acceptable to the 407 client, in order of preference, greatest to least. 409 5. Return result of running Compute Possible Keys (Section 4.1) on 410 sorted-variants, an empty string and an empty list. 412 This returns a list of strings suitable for comparing to normalised 413 Variant-Keys (Section 3.1) that represent possible responses on the 414 server that can be used to satisfy the request, in preference order, 415 provided that their secondary cache key (after removing the headers 416 covered by Variants) matches. Section 4.2 illustrates one way to do 417 this. 419 4.1. Compute Possible Keys 421 This algorithm computes the cross-product of the elements of key- 422 facets. 424 Given key-facets (a list of lists), and key-stub (a string 425 representing a partial key), and possible-keys (a list): 427 1. Let values be the first member of key-facets. 429 2. For each value in values: 431 1. If key-stub is an empty string, let this-key be a copy of 432 value. 434 2. Otherwise: 436 1. Let this-key be a copy of key-stub. 438 2. Append a comma (",") to this-key. 440 3. Append value to this-key. 442 3. Let remaining-facets be a copy of all of the members of key- 443 facets except the first. 445 4. If remaining-facets is empty, append this-key to possible- 446 keys. 448 5. Otherwise, run Compute Possible Keys on remaining-facets, 449 this-key and possible-keys. 451 3. Return possible-keys. 453 4.2. Check Vary 455 This algorithm is an example of how an implementation can meet the 456 requirement to apply the members of the Vary header field that are 457 not covered by Variants. 459 Given stored-response (a stored response): 461 1. Let filtered-vary be the field-value(s) of stored-response's 462 "Vary" header field. 464 2. Let processed-variants be a list containing the request header 465 fields that identify the content negotiation mechanisms supported 466 by the implementation. 468 3. Remove any member of filtered-vary that is a case-insensitive 469 match for a member of processed-variants. 471 4. If the secondary cache key (as calculated in [RFC7234], 472 Section 4.1) for stored_response matches incoming-request, using 473 filtered-vary for the value of the "Vary" response header, return 474 True. 476 5. Return False. 478 This returns a Boolean that indicates whether stored-response can be 479 used to satisfy the request. 481 Note that implementation of the Vary header field varies in practice, 482 and the algorithm above illustrates only one way to apply it. It is 483 equally viable to forward the request if there is a request header 484 listed in Vary but not Variants. 486 4.3. Example of Cache Behaviour 488 For example, if the selected variants-header was: 490 Variants: Accept-Language;en;fr,de, Accept-Encoding;gzip;br 492 and the request contained the headers: 494 Accept-Language: fr;q=1.0, en;q=0.1 495 Accept-Encoding: gzip 497 Then the sorted-variants would be: 499 [ 500 ["fr", "en"] // prefers French, will accept English 501 ["gzip", "identity"] // prefers gzip encoding, will accept identity 502 ] 504 Which means that the sorted-keys would be: 506 [ 507 'fr gzip', 508 'fr identity', 509 'en gzip', 510 'en identity' 511 ] 513 Representing a first preference of a French, gzip'd response. Thus, 514 if a cache has a response with: 516 Variant-Key: fr, gzip 518 it could be used to satisfy the first preference. If not, responses 519 corresponding to the other keys could be returned, or the request 520 could be forwarded towards the origin. 522 5. Origin Server Behaviour 524 Origin servers that wish to take advantage of Variants will need to 525 generate both the Variants (Section 2) and Variant-Key (Section 3) 526 header fields in all cacheable responses for a given resource. If 527 either is omitted and the response is stored, it will have the effect 528 of disabling caching for that resource until it is no longer stored 529 (e.g., it expires, or is evicted). 531 Likewise, origin servers will need to assure that the members of both 532 header field values are in the same order and have the same length, 533 since discrepancies will cause caches to avoid using the responses 534 they occur in. 536 The value of the Variants header should be relatively stable for a 537 given resource over time; when it changes, it can have the effect of 538 invalidating previously stored responses. 540 As per Section 2.1, the Vary header is required to be set 541 appropriately when Variants is in use, so that caches that do not 542 implement this specification still operate correctly. 544 Origin servers are advised to carefully consider which content 545 negotiation mechanisms to enumerate in Variants; if a mechanism is 546 not supported by a receiving cache, it will "downgrade" to Vary 547 handling, which can negatively impact cache efficiency. 549 5.1. Examples 551 The operation of Variants is illustrated by the examples below. 553 5.1.1. Single Variant 555 Given a request/response pair: 557 GET /clancy HTTP/1.1 558 Host: www.example.com 559 Accept-Language: en;q=1.0, fr;q=0.5 561 HTTP/1.1 200 OK 562 Content-Type: image/gif 563 Content-Language: en 564 Cache-Control: max-age=3600 565 Variants: Accept-Language;en;de 566 Variant-Key: en 567 Vary: Accept-Language 568 Transfer-Encoding: chunked 569 Upon receipt of this response, the cache knows that two 570 representations of this resource are available, one with a language 571 of "en", and another whose language is "de". 573 Subsequent requests (while this response is fresh) will cause the 574 cache to either reuse this response or forward the request, depending 575 on what the selection algorithm determines. 577 So, if a request with "en" in Accept-Language is received and its 578 q-value indicates that it is acceptable, the stored response is used. 579 A request that indicates that "de" is acceptable will be forwarded to 580 the origin, thereby populating the cache. A cache receiving a 581 request that indicates both languages are acceptable will use the 582 q-value to make a determination of what response to return. 584 A cache receiving a request that does not list either language as 585 acceptable (or does not contain an Accept-Language at all) will 586 return the "en" representation (possibly fetching it from the 587 origin), since it is listed first in the Variants list. 589 Note that Accept-Language is listed in Vary, to assure backwards- 590 compatibility with caches that do not support Variants. 592 5.1.2. Multiple Variants 594 A more complicated request/response pair: 596 GET /murray HTTP/1.1 597 Host: www.example.net 598 Accept-Language: en;q=1.0, fr;q=0.5 599 Accept-Encoding: gzip, br 601 HTTP/1.1 200 OK 602 Content-Type: image/gif 603 Content-Language: en 604 Content-Encoding: br 605 Variants: Accept-Language;en;jp;de 606 Variants: Accept-Encoding;br;gzip 607 Variant-Key: en, br 608 Vary: Accept-Language, Accept-Encoding 609 Transfer-Encoding: chunked 611 Here, the cache knows that there are two axes that the response 612 varies upon; language and encoding. Thus, there are a total of nine 613 possible representations for the resource (including the identity 614 encoding), and the cache needs to consider the selection algorithms 615 for both axes. 617 Upon a subsequent request, if both selection algorithms return a 618 stored representation, it can be served from cache; otherwise, the 619 request will need to be forwarded to origin. 621 5.1.3. Partial Coverage 623 Now, consider the previous example, but where only one of the Vary'd 624 axes (encoding) is listed in Variants: 626 GET /bar HTTP/1.1 627 Host: www.example.net 628 Accept-Language: en;q=1.0, fr;q=0.5 629 Accept-Encoding: gzip, br 631 HTTP/1.1 200 OK 632 Content-Type: image/gif 633 Content-Language: en 634 Content-Encoding: br 635 Variants: Accept-Encoding;br;gzip 636 Variant-Key: br 637 Vary: Accept-Language, Accept-Encoding 638 Transfer-Encoding: chunked 640 Here, the cache will need to calculate a secondary cache key as per 641 [RFC7234], Section 4.1 - but considering only Accept-Language to be 642 in its field-value - and then continue processing Variants for the 643 set of stored responses that the algorithm described there selects. 645 6. Defining Content Negotiation Using Variants 647 To be usable with Variants, proactive content negotiation mechanisms 648 need to be specified to take advantage of it. Specifically, they: 650 o MUST define a request header field that advertises the clients 651 preferences or capabilities, whose field-name SHOULD begin with 652 "Accept-". 654 o MUST define the syntax of an available-value that will occur in 655 Variants and Variant-Key. 657 o MUST define an algorithm for selecting a result. It MUST return a 658 list of available-values that are suitable for the request, in 659 order of preference, given the value of the request header 660 nominated above and an available-values list from the Variants 661 header. If the result is an empty list, it implies that the cache 662 cannot satisfy the request. 664 Appendix A fulfils these requirements for some existing proactive 665 content negotiation mechanisms in HTTP. 667 7. IANA Considerations 669 This specification registers two values in the Permanent Message 670 Header Field Names registry established by [RFC3864]: 672 o Header field name: Variants 674 o Applicable protocol: http 676 o Status: standard 678 o Author/Change Controller: IETF 680 o Specification document(s): [this document] 682 o Related information: 684 o Header field name: Variant-Key 686 o Applicable protocol: http 688 o Status: standard 690 o Author/Change Controller: IETF 692 o Specification document(s): [this document] 694 o Related information: 696 8. Security Considerations 698 If the number or advertised characteristics of the representations 699 available for a resource are considered sensitive, the Variants 700 header by its nature will leak them. 702 Note that the Variants header is not a commitment to make 703 representations of a certain nature available; the runtime behaviour 704 of the server always overrides hints like Variants. 706 9. References 707 9.1. Normative References 709 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 710 Requirement Levels", BCP 14, RFC 2119, 711 DOI 10.17487/RFC2119, March 1997, 712 . 714 [RFC4647] Phillips, A. and M. Davis, "Matching of Language Tags", 715 BCP 47, RFC 4647, DOI 10.17487/RFC4647, September 2006, 716 . 718 [RFC5234] Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax 719 Specifications: ABNF", STD 68, RFC 5234, 720 DOI 10.17487/RFC5234, January 2008, 721 . 723 [RFC7230] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer 724 Protocol (HTTP/1.1): Message Syntax and Routing", 725 RFC 7230, DOI 10.17487/RFC7230, June 2014, 726 . 728 [RFC7231] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer 729 Protocol (HTTP/1.1): Semantics and Content", RFC 7231, 730 DOI 10.17487/RFC7231, June 2014, 731 . 733 [RFC7234] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, 734 Ed., "Hypertext Transfer Protocol (HTTP/1.1): Caching", 735 RFC 7234, DOI 10.17487/RFC7234, June 2014, 736 . 738 [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 739 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, 740 May 2017, . 742 9.2. Informative References 744 [I-D.ietf-httpbis-client-hints] 745 Grigorik, I., "HTTP Client Hints", draft-ietf-httpbis- 746 client-hints-05 (work in progress), January 2018. 748 [RFC2295] Holtman, K. and A. Mutz, "Transparent Content Negotiation 749 in HTTP", RFC 2295, DOI 10.17487/RFC2295, March 1998, 750 . 752 [RFC3864] Klyne, G., Nottingham, M., and J. Mogul, "Registration 753 Procedures for Message Header Fields", BCP 90, RFC 3864, 754 DOI 10.17487/RFC3864, September 2004, 755 . 757 9.3. URIs 759 [1] https://lists.w3.org/Archives/Public/ietf-http-wg/ 761 [2] https://httpwg.github.io/ 763 [3] https://github.com/httpwg/http-extensions/labels/variants 765 [4] https://github.com/mnot/variants-toy 767 Appendix A. Variants for Existing Content Negotiation Mechanisms 769 This appendix defines the required information to use existing 770 proactive content negotiation mechanisms (as defined in [RFC7231], 771 Section 5.3) with the Variants header field. 773 A.1. Accept 775 This section defines variant handling for the Accept request header 776 (section 5.3.2 of [RFC7231]). 778 The syntax of an available-value for Accept is: 780 accept-available-value = type "/" subtype 782 To perform content negotiation for Accept given a request-value and 783 available-values: 785 1. Let preferred-available be an empty list. 787 2. Let preferred-types be a list of the types in the request-value, 788 ordered by their weight, highest to lowest, as per Section 5.3.2 789 of [RFC7231] (omitting any coding with a weight of 0). If 790 "Accept" is not present or empty, preferred-types will be empty. 791 If a type lacks an explicit weight, an implementation MAY assign 792 one. 794 3. If the first member of available-values is not a member of 795 preferred-types, append it to preferred-types (thus making it the 796 default). 798 4. For each preferred-type in preferred-types: 800 1. If any member of available-values matches preferred-type, 801 using the media-range matching mechanism specified in 802 Section 5.3.2 of [RFC7231] (which is case-insensitive), 803 append those members of available-values to preferred- 804 available (preserving the precedence order implied by the 805 media ranges' specificity). 807 5. Return preferred-available. 809 Note that this algorithm explicitly ignores extension parameters on 810 media types (e.g., "charset"). 812 A.2. Accept-Encoding 814 This section defines variant handling for the Accept-Encoding request 815 header (section 5.3.4 of [RFC7231]). 817 The syntax of an available-value for Accept-Encoding is: 819 accept-encoding-available-value = content-coding / "identity" 821 To perform content negotiation for Accept-Encoding given a request- 822 value and available-values: 824 1. Let preferred-available be an empty list. 826 2. Let preferred-codings be a list of the codings in the request- 827 value, ordered by their weight, highest to lowest, as per 828 Section 5.3.1 of [RFC7231] (omitting any coding with a weight of 829 0). If "Accept-Encoding" is not present or empty, preferred- 830 codings will be empty. If a coding lacks an explicit weight, an 831 implementation MAY assign one. 833 3. If "identity" is not a member of preferred-codings, append 834 "identity". 836 4. Append "identity" to available-values. 838 5. For each preferred-coding in preferred-codings: 840 1. If there is a case-insensitive, character-for-character match 841 for preferred-coding in available-values, append that member 842 of available-values to preferred-available. 844 6. Return preferred-available. 846 Note that the unencoded variant needs to have a Variant-Key header 847 field with a value of "identity" (as defined in Section 5.3.4 of 848 [RFC7231]). 850 A.3. Accept-Language 852 This section defines variant handling for the Accept-Language request 853 header (section 5.3.5 of [RFC7231]). 855 The syntax of an available-value for Accept-Language is: 857 accept-encoding-available-value = language-range 859 To perform content negotiation for Accept-Language given a request- 860 value and available-values: 862 1. Let preferred-available be an empty list. 864 2. Let preferred-langs be a list of the language-ranges in the 865 request-value, ordered by their weight, highest to lowest, as per 866 Section 5.3.1 of [RFC7231] (omitting any language-range with a 867 weight of 0). If a language-range lacks a weight, an 868 implementation MAY assign one. 870 3. If the first member of available-values is not a member of 871 preferred-langs, append it to preferred-langs (thus making it the 872 default). 874 4. For each preferred-lang in preferred-langs: 876 1. If any member of available-values matches preferred-lang, 877 using either the Basic or Extended Filtering scheme defined 878 in Section 3.3 of [RFC4647], append those members of 879 available-values to preferred-available (preserving their 880 order). 882 5. Return preferred-available. 884 Acknowledgements 886 This protocol is conceptually similar to, but simpler than, 887 Transparent Content Negotiation [RFC2295]. Thanks to its authors for 888 their inspiration. 890 It is also a generalisation of a Fastly VCL feature designed by 891 Rogier 'DocWilco' Mulhuijzen. 893 Thanks to Hooman Beheshti, Ilya Grigorik and Jeffrey Yasskin for 894 their review and input. 896 Author's Address 898 Mark Nottingham 899 Fastly 901 Email: mnot@mnot.net 902 URI: https://www.mnot.net/