idnits 2.17.1 draft-ietf-httpbis-variants-01.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 (May 1, 2018) is 2159 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 763 -- Looks like a reference, but probably isn't: '2' on line 765 -- Looks like a reference, but probably isn't: '3' on line 767 -- Looks like a reference, but probably isn't: '4' on line 769 ** 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) May 1, 2018 5 Intended status: Standards Track 6 Expires: November 2, 2018 8 HTTP Representation Variants 9 draft-ietf-httpbis-variants-01 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 November 2, 2018. 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 . . . . . . . . . . . . . 6 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 . . . . . . . . . . . . . . . . . . . 11 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 . . . . . . . . . . . . . . . . . . 13 82 6. Defining Content Negotiation Using Variants . . . . . . . . . 14 83 7. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 14 84 8. Security Considerations . . . . . . . . . . . . . . . . . . . 15 85 9. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 15 86 10. References . . . . . . . . . . . . . . . . . . . . . . . . . 15 87 10.1. Normative References . . . . . . . . . . . . . . . . . . 16 88 10.2. Informative References . . . . . . . . . . . . . . . . . 16 89 10.3. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 17 90 Appendix A. Variants for Existing Content Negotiation Mechanisms 17 91 A.1. Accept . . . . . . . . . . . . . . . . . . . . . . . . . 17 92 A.2. Accept-Encoding . . . . . . . . . . . . . . . . . . . . . 18 93 A.3. Accept-Language . . . . . . . . . . . . . . . . . . . . . 18 94 Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 19 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 Content-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: fr 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 a French 135 representation is available and might be able to infer that an 136 English representation is not available. But, it does not know (for 137 example) whether a Japanese representation is available without 138 making another 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: fr 159 Vary: Accept-Language 160 Variants: Accept-Language;fr;de;en;jp 161 Variant-Key: fr 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]. 198 2. The "Variants" HTTP Header Field 200 The Variants HTTP response header field indicates what 201 representations are available for a given resource at the time that 202 the response is produced, by enumerating the request header fields 203 that it varies on, along with the values that are available for each. 205 Variants = 1#variant-item 206 variant-item = field-name *( OWS ";" OWS available-value ) 207 available-value = token 209 Each "variant-item" indicates a request header field that carries a 210 value that clients might proactively negotiate for; each parameter on 211 it indicates a value for which there is an available representation 212 on the origin server. 214 So, given this example header field: 216 Variants: Accept-Encoding;gzip 218 a recipient can infer that the only content-coding available for that 219 resource is "gzip" (along with the "identity" non-encoding; see 220 Appendix A.2). 222 Given: 224 Variants: accept-encoding 226 a recipient can infer that no content-codings (beyond identity) are 227 supported. Note that as always, field-name is case-insensitive. 229 A more complex example: 231 Variants: Accept-Encoding;gzip;br, Accept-Language;en ;fr 233 Here, recipients can infer that two content-codings in addition to 234 "identity" are available, as well as two content languages. Note 235 that, as with all HTTP header fields that use the "#" list rule (see 236 [RFC7230], Section 7), they might occur in the same header field or 237 separately, like this: 239 Variants: Accept-Encoding;gzip;brotli 240 Variants: Accept-Language;en ;fr 242 The ordering of available-values after the field-name is significant, 243 as it might be used by the header's algorithm for selecting a 244 response (in this example, the first language is the default; see 245 Appendix A.3). 247 The ordering of the request header fields themselves indicates 248 descending application of preferences; in the example above, a cache 249 that has all of the possible permutations stored will honour the 250 client's preferences for Accept-Encoding before honouring Accept- 251 Language. 253 Origin servers SHOULD consistently send Variant header fields on all 254 cacheable (as per [RFC7234], Section 3) responses for a resource, 255 since its absence will trigger caches to fall back to Vary 256 processing. 258 Likewise, servers MUST send the Variant-Key response header field 259 when sending Variants, since its absence means that the stored 260 response will not be reused when this specification is implemented. 262 2.1. Relationship to Vary 264 Caches that implement this specification SHOULD ignore request header 265 fields in the Vary header for the purposes of secondary cache key 266 calculation ([RFC7234], Section 4.1) when their semantics are 267 implemented as per this specification and their corresponding 268 response header field is listed in Variants. 270 If any member of the Vary header does not have a corresponding 271 variant that is understood by the implementation, it is still subject 272 to the requirements there. 274 See Section 5.1.3 for an example. 276 In practice, implementation of Vary varies considerably. As a 277 result, cache efficiency might drop considerably when Variants does 278 not contain all of the headers referenced by Vary, because some 279 implementations might choose to disable Variants processing when this 280 is the case. 282 3. The "Variant-Key" HTTP Header Field 284 The Variant-Key HTTP response header field is used to indicate the 285 values from the Variants header field that identify the 286 representation it occurs within. 288 Variant-Key = available-values 289 available-values = available-value *( ";" available-value ) 291 Each member of the list contains the selected available-value(s), in 292 the same order as the variants listed in the Variants header field. 294 Therefore, Variant-Key MUST be the same length (in comma-separated 295 members) as Variants, and each member MUST correspond in position to 296 its companion in Variants. 298 For example: 300 Variants: Accept-Encoding;gzip;br, Accept-Language;en ;fr 301 Variant-Key: gzip, fr 303 This header pair indicates that the representation has a "gzip" 304 content-coding and "fr" content-language. 306 A more complex example involves listing multiple available-values in 307 a list member, to indicate that the response can be used to satisfy 308 requests with any of those values. For example: 310 Variants: Content-Encoding;gzip;br, Content-Language;en ;fr 311 Variant-Key: gzip;identity, fr 313 indicates that this response can be used for requests whose Content- 314 Encoding algorithm selects "gzip" or "identity", as long as the 315 Content-Language algorithm selects "fr" - perhaps because there is no 316 gzip-compressed French representation. 318 This highlights an important aspect of Variant-Key; it is only used 319 to indicate what request attributes are associated with the response 320 containing it; this is different from headers like Content-Encoding, 321 which indicate attributes of the response itself. 323 3.1. Generating a Variant-Key List 325 This algorithm generates a list of normalised strings from Variant- 326 Key, suitable for comparison with values generated by Section 4. 328 Given stored-headers, a set of headers from a stored response, a 329 normalised list of variant-keys for that message can be generated by: 331 1. Let variant-keys be an empty list. 333 2. Let variant-key-header be a string, the result of selecting all 334 field-values of stored-headers whose field-name is "Variant-Key" 335 and joining them with a comma (","). 337 3. Let value-list be the result of splitting variant-key-header on 338 commas (","). 340 4. For each value in value-list: 342 1. Remove all whitespace from value. 344 2. Let items be the result of splitting value on ";". 346 3. append items to variant-keys. 348 5. Return the result of running Compute Possible Keys (Section 4.1) 349 on variant-keys, an empty string and an empty list. 351 4. Cache Behaviour 353 Caches that implement the Variants header field and the relevant 354 semantics of the field-name it contains can use that knowledge to 355 either select an appropriate stored representation, or forward the 356 request if no appropriate representation is stored. 358 They do so by running this algorithm (or its functional equivalent) 359 upon receiving a request: 361 Given incoming-request, a mapping of field-names to lists of field 362 values, and stored-responses, a list of stored responses suitable for 363 reuse as defined in [RFC7234] Section 4, excepting the requirement to 364 calculate a secondary cache key: 366 1. If stored-responses is empty, return an empty list. 368 2. Order stored-responses by the "Date" header field, most recent to 369 least recent. 371 3. Let sorted-variants be an empty list. 373 4. If the freshest member of stored-responses (as per [RFC7234], 374 Section 4.2) has one or more "Variants" header field(s): 376 1. Select one member of stored-responses and let its "Variants" 377 header field-value(s) be variants-header. This SHOULD be the 378 most recent response, but MAY be from an older one as long as 379 it is still fresh. 381 2. For each variant in variants-header: 383 1. If variant's field-name corresponds to the request header 384 field identified by a content negotiation mechanism that 385 the implementation supports: 387 1. Let request-value be the field-value(s) associated 388 with field-name in incoming-request. 390 2. Let available-values be a list containing all 391 available-value for variant. 393 3. Let sorted-values be the result of running the 394 algorithm defined by the content negotiation 395 mechanism with request-value and available-values. 397 4. Append sorted-values to sorted-variants. 399 At this point, sorted-variants will be a list of lists, each 400 member of the top-level list corresponding to a variant-item 401 in the Variants header field-value, containing zero or more 402 items indicating available-values that are acceptable to the 403 client, in order of preference, greatest to least. 405 5. Return result of running Compute Possible Keys (Section 4.1) on 406 sorted-variants, an empty string and an empty list. 408 This returns a list of strings suitable for comparing to normalised 409 Variant-Keys (Section 3.1) that represent possible responses on the 410 server that can be used to satisfy the request, in preference order, 411 provided that their secondary cache key (after removing the headers 412 covered by Variants) matches. Section 4.2 illustrates one way to do 413 this. 415 4.1. Compute Possible Keys 417 Given key-facets, a list of lists, and key-stub, a string 418 representing a partial key, and possible-keys, a list: 420 1. Let values be the first member of key-facets. 422 2. For each value in values: 424 1. If key-stub is an empty string, let this-key be a copy of 425 value. 427 2. Otherwise: 429 1. Let this-key be a copy of key-stub. 431 2. Append a comma (",") to this-key. 433 3. Append value to this-key. 435 3. Let remaining-facets be a copy of all of the members of key- 436 facets except the first. 438 4. If remaining-facets is empty, append this-key to possible- 439 keys. 441 5. Otherwise, run Find Available Keys on remaining-facets, this- 442 key and possible-keys. 444 3. Return possible-keys. 446 4.2. Check Vary 448 This algorithm is an example of how an implementation can meet the 449 requirement to apply the members of the Vary header field that are 450 not covered by Variants. 452 Given a stored response, stored-response: 454 1. Let filtered-vary be the field-value(s) of stored-response's 455 "Vary" header field. 457 2. Let processed-variants be a list containing the request header 458 fields that identify the content negotiation mechanisms supported 459 by the implementation. 461 3. Remove any member of filtered-vary that is a case-insensitive 462 match for a member of processed-variants. 464 4. If the secondary cache key (as calculated in [RFC7234], 465 Section 4.1) for stored_response matches incoming-request, using 466 filtered-vary for the value of the "Vary" response header, return 467 True. 469 5. Return False. 471 This returns a Boolean that indicates whether stored-response can be 472 used to satisfy the request. 474 Note that implementation of the Vary header field varies in practice, 475 and the algorithm above illustrates only one way to apply it. It is 476 equally viable to forward the request if there is a request header 477 listed in Vary but not Variants. 479 4.3. Example of Cache Behaviour 481 For example, if the selected variants-header was: 483 Variants: Accept-Language;en;fr,de, Accept-Encoding;gzip,br 485 and the request contained the headers: 487 Accept-Language: fr;q=1.0, en;q=0.1 488 Accept-Encoding: gzip 490 Then the sorted-variants would be: 492 [ 493 ["fr", "en"] // prefers French, will accept English 494 ["gzip", "identity"] // prefers gzip encoding, will accept identity 495 ] 497 Which means that the sorted-keys would be: 499 [ 500 'fr gzip', 501 'fr identity', 502 'en gzip', 503 'en identity' 504 ] 506 Representing a first preference of a French, gzip'd response. Thus, 507 if a cache has a response with: 509 Variant-Key: fr, gzip 511 it could be used to satisfy the first preference. If not, responses 512 corresponding to the other keys could be returned, or the request 513 could be forwarded towards the origin. 515 5. Origin Server Behaviour 517 Origin servers that wish to take advantage of Variants will need to 518 generate both the Variants (Section 2) and Variant-Key (Section 3) 519 header fields in all cacheable responses for a given resource. If 520 either is omitted and the response is stored, it will have the effect 521 of disabling caching for that resource until it is no longer stored 522 (e.g., it expires, or is evicted). 524 Likewise, origin servers will need to assure that the members of both 525 header field values are in the same order and have the same length, 526 since discrepancies will cause caches to avoid using the responses 527 they occur in. 529 The value of the Variants header should be relatively stable for a 530 given resource over time; when it changes, it can have the effect of 531 invalidating previously stored responses. 533 As per Section 2.1, the Vary header is required to be set 534 appropriately when Variants is in use, so that caches that do not 535 implement this specification still operate correctly. 537 Origin servers are advised to carefully consider which content 538 negotiation mechanisms to enumerate in Variants; if a mechanism is 539 not supported by a receiving cache, it will "downgrade" to Vary 540 handling, which can negatively impact cache efficiency. 542 5.1. Examples 544 The operation of Variants is illustrated by the examples below. 546 5.1.1. Single Variant 548 Given a request/response pair: 550 GET /clancy HTTP/1.1 551 Host: www.example.com 552 Accept-Language: en;q=1.0, fr;q=0.5 554 HTTP/1.1 200 OK 555 Content-Type: image/gif 556 Content-Language: en 557 Cache-Control: max-age=3600 558 Variants: Accept-Language;en;de 559 Variant-Key: en 560 Vary: Accept-Language 561 Transfer-Encoding: chunked 563 Upon receipt of this response, the cache knows that two 564 representations of this resource are available, one with a Content- 565 Language of "en", and another whose Content-Language is "de". 567 Subsequent requests (while this response is fresh) will cause the 568 cache to either reuse this response or forward the request, depending 569 on what the selection algorithm determines. 571 So, if a request with "en" in Accept-Language is received and its 572 q-value indicates that it is acceptable, the stored response is used. 573 A request that indicates that "de" is acceptable will be forwarded to 574 the origin, thereby populating the cache. A cache receiving a 575 request that indicates both languages are acceptable will use the 576 q-value to make a determination of what response to return. 578 A cache receiving a request that does not list either language as 579 acceptable (or does not contain an Accept-Language at all) will 580 return the "en" representation (possibly fetching it from the 581 origin), since it is listed first in the Variants list. 583 Note that Accept-Language is listed in Vary, to assure backwards- 584 compatibility with caches that do not support Variants. 586 5.1.2. Multiple Variants 588 A more complicated request/response pair: 590 GET /murray HTTP/1.1 591 Host: www.example.net 592 Accept-Language: en;q=1.0, fr;q=0.5 593 Accept-Encoding: gzip, br 595 HTTP/1.1 200 OK 596 Content-Type: image/gif 597 Content-Language: en 598 Content-Encoding: br 599 Variants: Accept-Language;en;jp;de 600 Variants: Accept-Encoding;br;gzip 601 Variant-Key: en, br 602 Vary: Accept-Language, Accept-Encoding 603 Transfer-Encoding: chunked 605 Here, the cache knows that there are two axes that the response 606 varies upon; Content-Language and Content-Encoding. Thus, there are 607 a total of nine possible representations for the resource (including 608 the identity encoding), and the cache needs to consider the selection 609 algorithms for both axes. 611 Upon a subsequent request, if both selection algorithms return a 612 stored representation, it can be served from cache; otherwise, the 613 request will need to be forwarded to origin. 615 5.1.3. Partial Coverage 617 Now, consider the previous example, but where only one of the Vary'd 618 axes (Content-Encoding) is listed in Variants: 620 GET /bar HTTP/1.1 621 Host: www.example.net 622 Accept-Language: en;q=1.0, fr;q=0.5 623 Accept-Encoding: gzip, br 625 HTTP/1.1 200 OK 626 Content-Type: image/gif 627 Content-Language: en 628 Content-Encoding: br 629 Variants: Accept-Encoding;br;gzip 630 Variant-Key: br 631 Vary: Accept-Language, Accept-Encoding 632 Transfer-Encoding: chunked 634 Here, the cache will need to calculate a secondary cache key as per 635 [RFC7234], Section 4.1 - but considering only Accept-Language to be 636 in its field-value - and then continue processing Variants for the 637 set of stored responses that the algorithm described there selects. 639 6. Defining Content Negotiation Using Variants 641 To be usable with Variants, proactive content negotiation mechanisms 642 need to be specified to take advantage of it. Specifically, they: 644 o MUST define a request header field that advertises the clients 645 preferences or capabilities, whose field-name SHOULD begin with 646 "Accept-". 648 o MUST define the syntax of available-values that will occur in 649 Variants and Variant-Key. 651 o MUST define an algorithm for selecting a result. It MUST return a 652 list of available-values that are suitable for the request, in 653 order of preference, given the value of the request header 654 nominated above and an available-values list from the Variants 655 header. If the result is an empty list, it implies that the cache 656 cannot satisfy the request. 658 Appendix A fulfils these requirements for some existing proactive 659 content negotiation mechanisms in HTTP. 661 7. IANA Considerations 663 This specification registers two values in the Permanent Message 664 Header Field Names registry established by [RFC3864]: 666 o Header field name: Variants 667 o Applicable protocol: http 669 o Status: standard 671 o Author/Change Controller: IETF 673 o Specification document(s): [this document] 675 o Related information: 677 o Header field name: Variant-Key 679 o Applicable protocol: http 681 o Status: standard 683 o Author/Change Controller: IETF 685 o Specification document(s): [this document] 687 o Related information: 689 8. Security Considerations 691 If the number or advertised characteristics of the representations 692 available for a resource are considered sensitive, the Variants 693 header by its nature will leak them. 695 Note that the Variants header is not a commitment to make 696 representations of a certain nature available; the runtime behaviour 697 of the server always overrides hints like Variants. 699 9. Acknowledgments 701 This protocol is conceptually similar to, but simpler than, 702 Transparent Content Negotiation [RFC2295]. Thanks to its authors for 703 their inspiration. 705 It is also a generalisation of a Fastly VCL feature designed by 706 Rogier 'DocWilco' Mulhuijzen. 708 Thanks to Hooman Beheshti for his review and input. 710 10. References 711 10.1. Normative References 713 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 714 Requirement Levels", BCP 14, RFC 2119, 715 DOI 10.17487/RFC2119, March 1997, 716 . 718 [RFC4647] Phillips, A. and M. Davis, "Matching of Language Tags", 719 BCP 47, RFC 4647, DOI 10.17487/RFC4647, September 2006, 720 . 722 [RFC5234] Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax 723 Specifications: ABNF", STD 68, RFC 5234, 724 DOI 10.17487/RFC5234, January 2008, 725 . 727 [RFC7230] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer 728 Protocol (HTTP/1.1): Message Syntax and Routing", 729 RFC 7230, DOI 10.17487/RFC7230, June 2014, 730 . 732 [RFC7231] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer 733 Protocol (HTTP/1.1): Semantics and Content", RFC 7231, 734 DOI 10.17487/RFC7231, June 2014, 735 . 737 [RFC7234] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, 738 Ed., "Hypertext Transfer Protocol (HTTP/1.1): Caching", 739 RFC 7234, DOI 10.17487/RFC7234, June 2014, 740 . 742 [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 743 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, 744 May 2017, . 746 10.2. Informative References 748 [I-D.ietf-httpbis-client-hints] 749 Grigorik, I., "HTTP Client Hints", draft-ietf-httpbis- 750 client-hints-05 (work in progress), January 2018. 752 [RFC2295] Holtman, K. and A. Mutz, "Transparent Content Negotiation 753 in HTTP", RFC 2295, DOI 10.17487/RFC2295, March 1998, 754 . 756 [RFC3864] Klyne, G., Nottingham, M., and J. Mogul, "Registration 757 Procedures for Message Header Fields", BCP 90, RFC 3864, 758 DOI 10.17487/RFC3864, September 2004, 759 . 761 10.3. URIs 763 [1] https://lists.w3.org/Archives/Public/ietf-http-wg/ 765 [2] https://httpwg.github.io/ 767 [3] https://github.com/httpwg/http-extensions/labels/variants 769 [4] https://github.com/mnot/variants-toy 771 Appendix A. Variants for Existing Content Negotiation Mechanisms 773 This appendix defines the required information to use existing 774 proactive content negotiation mechanisms (as defined in [RFC7231], 775 Section 5.3) with the Variants header field. 777 A.1. Accept 779 This section defines handling for Accept variants, as per [RFC7231] 780 Section 5.3.2. 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 [RFC7231] 789 Section 5.3.2 (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 [RFC7231] Section 5.3.2 (which is case-insensitive), append 803 those members of available-values to preferred-available 804 (preserving the precedence order implied by the media ranges' 805 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 handling for Accept-Encoding variants, as per 815 [RFC7231] Section 5.3.4. 817 To perform content negotiation for Accept-Encoding given a request- 818 value and available-values: 820 1. Let preferred-available be an empty list. 822 2. Let preferred-codings be a list of the codings in the request- 823 value, ordered by their weight, highest to lowest, as per 824 [RFC7231] Section 5.3.1 (omitting any coding with a weight of 0). 825 If "Accept-Encoding" is not present or empty, preferred-codings 826 will be empty. If a coding lacks an explicit weight, an 827 implementation MAY assign one. 829 3. If "identity" is not a member of preferred-codings, append 830 "identity". 832 4. Append "identity" to available-values. 834 5. For each preferred-coding in preferred-codings: 836 1. If there is a case-insensitive, character-for-character match 837 for preferred-coding in available-values, append that member 838 of available-values to preferred-available. 840 6. Return preferred-available. 842 Note that the unencoded variant needs to have a Variant-Key header 843 field with a value of "identity" (as defined in [RFC7231] 844 Section 5.3.4). 846 A.3. Accept-Language 848 This section defines handling for Accept-Language variants, as per 849 [RFC7231] Section 5.3.5. 851 To perform content negotiation for Accept-Language given a request- 852 value and available-values: 854 1. Let preferred-available be an empty list. 856 2. Let preferred-langs be a list of the language-ranges in the 857 request-value, ordered by their weight, highest to lowest, as per 858 [RFC7231] Section 5.3.1 (omitting any language-range with a 859 weight of 0). If a language-range lacks a weight, an 860 implementation MAY assign one. 862 3. If the first member of available-values is not a member of 863 preferred-langs, append it to preferred-langs (thus making it the 864 default). 866 4. For each preferred-lang in preferred-langs: 868 1. If any member of available-values matches preferred-lang, 869 using either the Basic or Extended Filtering scheme defined 870 in [RFC4647] Section 3.3, append those members of available- 871 values to preferred-available (preserving their order). 873 5. Return preferred-available. 875 Author's Address 877 Mark Nottingham 878 Fastly 880 Email: mnot@mnot.net 881 URI: https://www.mnot.net/