idnits 2.17.1 draft-ietf-httpbis-variants-04.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 (October 22, 2018) is 2014 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 760 -- Looks like a reference, but probably isn't: '2' on line 762 -- Looks like a reference, but probably isn't: '3' on line 764 -- Looks like a reference, but probably isn't: '4' on line 766 ** 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-06 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) October 22, 2018 5 Intended status: Standards Track 6 Expires: April 25, 2019 8 HTTP Representation Variants 9 draft-ietf-httpbis-variants-04 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 April 25, 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 . . . . . . . . . . . . . . . . . . . . . . . . . 16 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 [English 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 [English 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 a set of selected available-value(s) 294 that identify this representation, in the same order as the variants 295 listed in the Variants header field. 297 Therefore, each member of Variant-Key MUST be the same length (in 298 semicolon-separated members) as Variants, and each member's 299 available-values MUST correspond in position to their companions in 300 Variants. 302 For example: 304 Variants: Accept-Encoding;gzip;br, Accept-Language;en ;fr 305 Variant-Key: gzip;fr 307 This header pair indicates that the representation has a "gzip" 308 content-coding and "fr" content-language. 310 If the response can be used to satisfy more than one request), they 311 can be listed in additional members. For example: 313 Variants: Accept-Encoding;gzip;br, Accept-Language;en ;fr 314 Variant-Key: gzip;fr, identity;fr 316 indicates that this response can be used for requests whose Accept- 317 Encoding algorithm selects "gzip" or "identity", as long as the 318 Accept-Language algorithm selects "fr" - perhaps because there is no 319 gzip-compressed French representation. 321 When more than one Variant-Key value is in a response, the first one 322 present MUST indicate the variant-key for the response it occurs 323 within. 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. Append value to variant-keys. 349 5. Return variant-keys. 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 363 for reuse as defined in Section 4 of [RFC7234], excepting the 364 requirement to 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 variants-header 377 be its "Variants" header field-value(s). 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, parsed according to the 382 ABNF: 384 1. If variant's field-name corresponds to the request header 385 field identified by a content negotiation mechanism that 386 the implementation supports: 388 1. Let request-value be the field-value(s) associated 389 with field-name in incoming-request. 391 2. Let available-values be a list containing all 392 available-value for variant. 394 3. Let sorted-values be the result of running the 395 algorithm defined by the content negotiation 396 mechanism with request-value and available-values. 398 4. Append sorted-values to sorted-variants. 400 At this point, sorted-variants will be a list of lists, each 401 member of the top-level list corresponding to a variant-item 402 in the Variants header field-value, containing zero or more 403 items indicating available-values that are acceptable to the 404 client, in order of preference, greatest to least. 406 5. Return result of running Compute Possible Keys (Section 4.1) on 407 sorted-variants, an empty string and an empty list. 409 This returns a list of strings suitable for comparing to normalised 410 Variant-Keys (Section 3.1) that represent possible responses on the 411 server that can be used to satisfy the request, in preference order, 412 provided that their secondary cache key (after removing the headers 413 covered by Variants) matches. Section 4.2 illustrates one way to do 414 this. 416 4.1. Compute Possible Keys 418 This algorithm computes the cross-product of the elements of key- 419 facets. 421 Given key-facets (a list of lists), and key-stub (a string 422 representing a partial key), and possible-keys (a list): 424 1. Let values be the first member of key-facets. 426 2. For each value in values: 428 1. If key-stub is an empty string, let this-key be a copy of 429 value. 431 2. Otherwise: 433 1. Let this-key be a copy of key-stub. 435 2. Append a semicolon (";") to this-key. 437 3. Append value to this-key. 439 3. Let remaining-facets be a copy of all of the members of key- 440 facets except the first. 442 4. If remaining-facets is empty, append this-key to possible- 443 keys. 445 5. Otherwise, run Compute Possible Keys on remaining-facets, 446 this-key and possible-keys. 448 3. Return possible-keys. 450 4.2. Check Vary 452 This algorithm is an example of how an implementation can meet the 453 requirement to apply the members of the Vary header field that are 454 not covered by Variants. 456 Given stored-response (a stored response): 458 1. Let filtered-vary be the field-value(s) of stored-response's 459 "Vary" header field. 461 2. Let processed-variants be a list containing the request header 462 fields that identify the content negotiation mechanisms supported 463 by the implementation. 465 3. Remove any member of filtered-vary that is a case-insensitive 466 match for a member of processed-variants. 468 4. If the secondary cache key (as calculated in [RFC7234], 469 Section 4.1) for stored_response matches incoming-request, using 470 filtered-vary for the value of the "Vary" response header, return 471 True. 473 5. Return False. 475 This returns a Boolean that indicates whether stored-response can be 476 used to satisfy the request. 478 Note that implementation of the Vary header field varies in practice, 479 and the algorithm above illustrates only one way to apply it. It is 480 equally viable to forward the request if there is a request header 481 listed in Vary but not Variants. 483 4.3. Example of Cache Behaviour 485 For example, if the selected variants-header was: 487 Variants: Accept-Language;en;fr;de, Accept-Encoding;gzip;br 489 and the request contained the headers: 491 Accept-Language: fr;q=1.0, en;q=0.1 492 Accept-Encoding: gzip 494 Then the sorted-variants would be: 496 [ 497 ["fr", "en"] // prefers French, will accept English 498 ["gzip", "identity"] // prefers gzip encoding, will accept identity 499 ] 501 Which means that the sorted-keys would be: 503 [ 504 'fr gzip', 505 'fr identity', 506 'en gzip', 507 'en identity' 508 ] 510 Representing a first preference of a French, gzip'd response. Thus, 511 if a cache has a response with: 513 Variant-Key: fr, gzip 515 it could be used to satisfy the first preference. If not, responses 516 corresponding to the other keys could be returned, or the request 517 could be forwarded towards the origin. 519 5. Origin Server Behaviour 521 Origin servers that wish to take advantage of Variants will need to 522 generate both the Variants (Section 2) and Variant-Key (Section 3) 523 header fields in all cacheable responses for a given resource. If 524 either is omitted and the response is stored, it will have the effect 525 of disabling caching for that resource until it is no longer stored 526 (e.g., it expires, or is evicted). 528 Likewise, origin servers will need to assure that the members of both 529 header field values are in the same order and have the same length, 530 since discrepancies will cause caches to avoid using the responses 531 they occur in. 533 The value of the Variants header should be relatively stable for a 534 given resource over time; when it changes, it can have the effect of 535 invalidating previously stored responses. 537 As per Section 2.1, the Vary header is required to be set 538 appropriately when Variants is in use, so that caches that do not 539 implement this specification still operate correctly. 541 Origin servers are advised to carefully consider which content 542 negotiation mechanisms to enumerate in Variants; if a mechanism is 543 not supported by a receiving cache, it will "downgrade" to Vary 544 handling, which can negatively impact cache efficiency. 546 5.1. Examples 548 The operation of Variants is illustrated by the examples below. 550 5.1.1. Single Variant 552 Given a request/response pair: 554 GET /clancy HTTP/1.1 555 Host: www.example.com 556 Accept-Language: en;q=1.0, fr;q=0.5 558 HTTP/1.1 200 OK 559 Content-Type: image/gif 560 Content-Language: en 561 Cache-Control: max-age=3600 562 Variants: Accept-Language;en;de 563 Variant-Key: en 564 Vary: Accept-Language 565 Transfer-Encoding: chunked 566 Upon receipt of this response, the cache knows that two 567 representations of this resource are available, one with a language 568 of "en", and another whose language is "de". 570 Subsequent requests (while this response is fresh) will cause the 571 cache to either reuse this response or forward the request, depending 572 on what the selection algorithm determines. 574 So, if a request with "en" in Accept-Language is received and its 575 q-value indicates that it is acceptable, the stored response is used. 576 A request that indicates that "de" is acceptable will be forwarded to 577 the origin, thereby populating the cache. A cache receiving a 578 request that indicates both languages are acceptable will use the 579 q-value to make a determination of what response to return. 581 A cache receiving a request that does not list either language as 582 acceptable (or does not contain an Accept-Language at all) will 583 return the "en" representation (possibly fetching it from the 584 origin), since it is listed first in the Variants list. 586 Note that Accept-Language is listed in Vary, to assure backwards- 587 compatibility with caches that do not support Variants. 589 5.1.2. Multiple Variants 591 A more complicated request/response pair: 593 GET /murray HTTP/1.1 594 Host: www.example.net 595 Accept-Language: en;q=1.0, fr;q=0.5 596 Accept-Encoding: gzip, br 598 HTTP/1.1 200 OK 599 Content-Type: image/gif 600 Content-Language: en 601 Content-Encoding: br 602 Variants: Accept-Language;en;jp;de 603 Variants: Accept-Encoding;br;gzip 604 Variant-Key: en;br 605 Vary: Accept-Language, Accept-Encoding 606 Transfer-Encoding: chunked 608 Here, the cache knows that there are two axes that the response 609 varies upon; language and encoding. Thus, there are a total of nine 610 possible representations for the resource (including the identity 611 encoding), and the cache needs to consider the selection algorithms 612 for both axes. 614 Upon a subsequent request, if both selection algorithms return a 615 stored representation, it can be served from cache; otherwise, the 616 request will need to be forwarded to origin. 618 5.1.3. Partial Coverage 620 Now, consider the previous example, but where only one of the Vary'd 621 axes (encoding) is listed in Variants: 623 GET /bar HTTP/1.1 624 Host: www.example.net 625 Accept-Language: en;q=1.0, fr;q=0.5 626 Accept-Encoding: gzip, br 628 HTTP/1.1 200 OK 629 Content-Type: image/gif 630 Content-Language: en 631 Content-Encoding: br 632 Variants: Accept-Encoding;br;gzip 633 Variant-Key: br 634 Vary: Accept-Language, Accept-Encoding 635 Transfer-Encoding: chunked 637 Here, the cache will need to calculate a secondary cache key as per 638 [RFC7234], Section 4.1 - but considering only Accept-Language to be 639 in its field-value - and then continue processing Variants for the 640 set of stored responses that the algorithm described there selects. 642 6. Defining Content Negotiation Using Variants 644 To be usable with Variants, proactive content negotiation mechanisms 645 need to be specified to take advantage of it. Specifically, they: 647 o MUST define a request header field that advertises the clients 648 preferences or capabilities, whose field-name SHOULD begin with 649 "Accept-". 651 o MUST define the syntax of an available-value that will occur in 652 Variants and Variant-Key. 654 o MUST define an algorithm for selecting a result. It MUST return a 655 list of available-values that are suitable for the request, in 656 order of preference, given the value of the request header 657 nominated above and an available-values list from the Variants 658 header. If the result is an empty list, it implies that the cache 659 cannot satisfy the request. 661 Appendix A fulfils these requirements for some existing proactive 662 content negotiation mechanisms in HTTP. 664 7. IANA Considerations 666 This specification registers the following entry in the Permanent 667 Message Header Field Names registry established by [RFC3864]: 669 o Header field name: Variants 671 o Applicable protocol: http 673 o Status: standard 675 o Author/Change Controller: IETF 677 o Specification document(s): [this document] 679 o Related information: 681 This specification registers the following entry in the Permanent 682 Message Header Field Names registry established by [RFC3864]: 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 708 9.1. Normative References 710 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 711 Requirement Levels", BCP 14, RFC 2119, 712 DOI 10.17487/RFC2119, March 1997, 713 . 715 [RFC4647] Phillips, A. and M. Davis, "Matching of Language Tags", 716 BCP 47, RFC 4647, DOI 10.17487/RFC4647, September 2006, 717 . 719 [RFC5234] Crocker, D., Ed. and P. Overell, "Augmented BNF for Syntax 720 Specifications: ABNF", STD 68, RFC 5234, 721 DOI 10.17487/RFC5234, January 2008, 722 . 724 [RFC7230] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer 725 Protocol (HTTP/1.1): Message Syntax and Routing", 726 RFC 7230, DOI 10.17487/RFC7230, June 2014, 727 . 729 [RFC7231] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer 730 Protocol (HTTP/1.1): Semantics and Content", RFC 7231, 731 DOI 10.17487/RFC7231, June 2014, 732 . 734 [RFC7234] Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, 735 Ed., "Hypertext Transfer Protocol (HTTP/1.1): Caching", 736 RFC 7234, DOI 10.17487/RFC7234, June 2014, 737 . 739 [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 740 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, 741 May 2017, . 743 9.2. Informative References 745 [I-D.ietf-httpbis-client-hints] 746 Grigorik, I., "HTTP Client Hints", draft-ietf-httpbis- 747 client-hints-06 (work in progress), July 2018. 749 [RFC2295] Holtman, K. and A. Mutz, "Transparent Content Negotiation 750 in HTTP", RFC 2295, DOI 10.17487/RFC2295, March 1998, 751 . 753 [RFC3864] Klyne, G., Nottingham, M., and J. Mogul, "Registration 754 Procedures for Message Header Fields", BCP 90, RFC 3864, 755 DOI 10.17487/RFC3864, September 2004, 756 . 758 9.3. URIs 760 [1] https://lists.w3.org/Archives/Public/ietf-http-wg/ 762 [2] https://httpwg.github.io/ 764 [3] https://github.com/httpwg/http-extensions/labels/variants 766 [4] https://github.com/mnot/variants-toy 768 Appendix A. Variants for Existing Content Negotiation Mechanisms 770 This appendix defines the required information to use existing 771 proactive content negotiation mechanisms (as defined in [RFC7231], 772 Section 5.3) with the Variants header field. 774 A.1. Accept 776 This section defines variant handling for the Accept request header 777 (section 5.3.2 of [RFC7231]). 779 The syntax of an available-value for Accept is: 781 accept-available-value = type "/" subtype 783 To perform content negotiation for Accept given a request-value and 784 available-values: 786 1. Let preferred-available be an empty list. 788 2. Let preferred-types be a list of the types in the request-value, 789 ordered by their weight, highest to lowest, as per Section 5.3.2 790 of [RFC7231] (omitting any coding with a weight of 0). If 791 "Accept" is not present or empty, preferred-types will be empty. 792 If a type lacks an explicit weight, an implementation MAY assign 793 one. 795 3. If the first member of available-values is not a member of 796 preferred-types, append it to preferred-types (thus making it the 797 default). 799 4. For each preferred-type in preferred-types: 801 1. If any member of available-values matches preferred-type, 802 using the media-range matching mechanism specified in 803 Section 5.3.2 of [RFC7231] (which is case-insensitive), 804 append those members of available-values to preferred- 805 available (preserving the precedence order implied by the 806 media ranges' specificity). 808 5. Return preferred-available. 810 Note that this algorithm explicitly ignores extension parameters on 811 media types (e.g., "charset"). 813 A.2. Accept-Encoding 815 This section defines variant handling for the Accept-Encoding request 816 header (section 5.3.4 of [RFC7231]). 818 The syntax of an available-value for Accept-Encoding is: 820 accept-encoding-available-value = content-coding / "identity" 822 To perform content negotiation for Accept-Encoding given a request- 823 value and available-values: 825 1. Let preferred-available be an empty list. 827 2. Let preferred-codings be a list of the codings in the request- 828 value, ordered by their weight, highest to lowest, as per 829 Section 5.3.1 of [RFC7231] (omitting any coding with a weight of 830 0). If "Accept-Encoding" is not present or empty, preferred- 831 codings will be empty. If a coding lacks an explicit weight, an 832 implementation MAY assign one. 834 3. If "identity" is not a member of preferred-codings, append 835 "identity". 837 4. Append "identity" to available-values. 839 5. For each preferred-coding in preferred-codings: 841 1. If there is a case-insensitive, character-for-character match 842 for preferred-coding in available-values, append that member 843 of available-values to preferred-available. 845 6. Return preferred-available. 847 Note that the unencoded variant needs to have a Variant-Key header 848 field with a value of "identity" (as defined in Section 5.3.4 of 849 [RFC7231]). 851 A.3. Accept-Language 853 This section defines variant handling for the Accept-Language request 854 header (section 5.3.5 of [RFC7231]). 856 The syntax of an available-value for Accept-Language is: 858 accept-encoding-available-value = language-range 860 To perform content negotiation for Accept-Language given a request- 861 value and available-values: 863 1. Let preferred-available be an empty list. 865 2. Let preferred-langs be a list of the language-ranges in the 866 request-value, ordered by their weight, highest to lowest, as per 867 Section 5.3.1 of [RFC7231] (omitting any language-range with a 868 weight of 0). If a language-range lacks a weight, an 869 implementation MAY assign one. 871 3. If the first member of available-values is not a member of 872 preferred-langs, append it to preferred-langs (thus making it the 873 default). 875 4. For each preferred-lang in preferred-langs: 877 1. If any member of available-values matches preferred-lang, 878 using either the Basic or Extended Filtering scheme defined 879 in Section 3.3 of [RFC4647], append those members of 880 available-values to preferred-available (preserving their 881 order). 883 5. Return preferred-available. 885 Acknowledgements 887 This protocol is conceptually similar to, but simpler than, 888 Transparent Content Negotiation [RFC2295]. Thanks to its authors for 889 their inspiration. 891 It is also a generalisation of a Fastly VCL feature designed by 892 Rogier 'DocWilco' Mulhuijzen. 894 Thanks to Hooman Beheshti, Ilya Grigorik, Leif Hedstrom, and Jeffrey 895 Yasskin for their review and input. 897 Author's Address 899 Mark Nottingham 900 Fastly 902 Email: mnot@mnot.net 903 URI: https://www.mnot.net/