| Internet Engineering Task Force (IETF) | J. Snell |
| 请求评议:7240 | 2014年6月 |
| 类别:标准轨道 | |
| ISSN: 2070-1721 |
用于 HTTP 的 Prefer 首部
摘要
本规范定义了一个 HTTP 首部字段,客户端可使用该字段请求服务器在处理请求时采用某些特定行为。
本备忘录的状态
这是一个互联网标准轨道文档。
本文件是互联网工程任务组(IETF)的成果,代表 IETF 社区的共识。它已获得公开评审,并由互联网工程指导小组(IESG)批准发布。有关互联网标准的更多信息,请参见 RFC 5741 第2节。
关于本文档当前状态、任何勘误及如何提供反馈的信息,可从 http://www.rfc-editor.org/info/rfc7240 获取。
Copyright Notice
Copyright (c) 2014 IETF Trust and the persons identified as the document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License.
1. 引言
在处理 HTTP 请求的过程中,服务器或中间件通常会在一系列必需和可选行为之间作出选择。这些选择经常以各种微妙或明显的方式反映在响应中。
例如,当使用 HTTP PUT 方法修改资源时 —— 类似于 Atom Publishing Protocol 中的定义 [RFC5023] —— 服务器可以在返回已修改资源的完整表示或仅指示操作成功完成的最小响应之间进行选择。选择向客户端返回哪种响应类型通常并不影响请求的成功处理,但可能影响客户端在收到响应后必须采取的后续操作。也就是说,在响应中返回修改后资源的表示可以使客户端避免随后发送额外的 GET 请求。
类似地,处理请求的服务器经常面临关于如何处理在技术上无效或不正确但仍可理解的请求的决定。服务器可能可以忽略请求中的技术性错误但仍成功处理该请求。根据应用的具体要求和请求的性质,客户端可能认为这种宽容处理是合适的,也可能不这么认为。
尽管确切应用哪些行为的决定由处理请求的服务器负责,但服务器可能希望让客户端指定其偏好的可选行为。
当前,HTTP 没有为客户端就特定请求的可选处理方面表达偏好提供明确定义的手段。虽然 HTTP 提供了 Expect 首部 —— 可用于标识对请求处理的强制性期望 —— 但使用该字段来传达可选偏好存在问题:
- Expect 首部字段的语义要求中间件和服务器拒绝包含未识别或不被支持的期望的请求。
- 虽然 Expect 首部是端到端的,但 HTTP 规范要求该首部按跳处理(hop-by-hop)进行处理。也就是说,客户端和源服务器之间的每一个中间代理在处理请求时都必须处理该期望并判断自己是否能够适当地处理它。
Expect 的必须理解(must-understand)语义使其不适合作为表达可选偏好的工具。
客户端的另一种选择是使用请求 URI 的查询字符串参数来表达偏好。然而,任何改变 URI 的机制都可能带来不良影响,例如缓存记录被改变的 URI。
作为替代方案,本规范定义了一个新的 HTTP 请求首部字段,客户端可用它来请求服务器在处理请求时应用可选行为。此外,还定义了一些初始的偏好标记以供该首部使用。
本文中关键词 "MUST"、"MUST NOT"、"REQUIRED"、"SHALL"、"SHALL NOT"、"SHOULD"、"SHOULD NOT"、"RECOMMENDED"、"MAY" 和 "OPTIONAL" 均按 [RFC2119] 中的定义解释。
1.1. 语法表示法
2. Prefer 请求首部字段
Prefer 请求首部字段用于指示客户端偏好服务器采用某些特定行为,但这些行为并非成功完成请求所必需。Prefer 与 [RFC7231] 第 6.1.2 节定义的 Expect 首部性质相似,但服务器被允许忽略所声明的偏好。
ABNF:
Prefer = "Prefer" ":" 1#preference
preference = token [ BWS "=" BWS word ]
*( OWS ";" [ OWS parameter ] )
parameter = token [ BWS "=" BWS word ]
该首部字段采用可扩展语法,以便将来在“偏好注册表”(见 第 5.1 节)中增加值。服务器如果不识别或无法遵从请求中 Prefer 首部的某些偏好标记,必须忽略这些标记并继续处理,而不是报告错误。
偏好标记和参数中空或零长度的值等同于未指定值。因此,下面是等效的 "foo" 偏好且带有单一 "bar" 参数的示例:
Prefer: foo; bar
Prefer: foo; bar=""
Prefer: foo=""; bar
任何偏好标记都可以指定可选参数。参数的含义和应用取决于各偏好标记的定义以及服务器的实现。参数的顺序对其语义没有影响。
对偏好标记名和参数名的比较不区分大小写,而值区分大小写,无论其是 token 还是 quoted-string。
Prefer 首部字段是端到端的(end to end),如果请求被转发,代理 必须 转发该首部,除非 Prefer 已通过 [RFC7230] 第 6.1 节定义的 Connection 首部明确标识为逐跳(hop-by-hop)。
在某些情况下,代理可能决定自己能够独立于目标服务器满足某个偏好。例如,中间代理可能能够独立于源服务器通过返回 202 (Accepted) 来提供异步处理。此类代理可以自行选择是否在不依赖源服务器的情况下实现 "respond-async" 偏好。
各偏好标记可以定义是否以及如何允许中间件在不与源服务器协商的情况下独立地将偏好应用于请求的要求和限制。
客户端可以在单个消息中使用多个 Prefer 首部字段,或者使用一个 Prefer 首部字段并以逗号分隔列出多个偏好标记。如果使用了多个 Prefer 首部字段,其效果等同于将所有标记以逗号连接合并为一个 Prefer 首部。例如,以下两种写法是等价的:
使用多个 Prefer 首部字段,定义三个不同偏好标记的情况:
POST /foo HTTP/1.1 Host: example.org Prefer: respond-async, wait=100 Prefer: handling=lenient Date: Tue, 20 Dec 2011 12:34:56 GMT
使用单个 Prefer 首部字段,定义相同三个偏好标记的情况:
POST /foo HTTP/1.1 Host: example.org Prefer: handling=lenient, wait=100, respond-async Date: Tue, 20 Dec 2011 12:34:56 GMT
为避免歧义,不应在单个请求中多次出现相同的偏好标记。如果某个偏好被多次指定,只应考虑第一次出现的实例。所有随后的出现 应当 被忽略,且不应报告错误或以其他方式改变请求的处理。这是偏好顺序唯一会被视为具有意义的情况。
由于在正确实现服务器驱动的内容协商、有效缓存和可选偏好应用方面存在固有复杂性,开发者在以影响响应缓存的方式使用偏好时应谨慎,并且 不应 使用 Prefer 机制进行内容协商。如果服务器支持可选应用的偏好并且该偏好可能导致缓存对响应实体的处理有所不同,则响应中 必须 包含 Vary 首部字段,列出 Prefer 首部字段,无论客户端是否在请求中实际使用了 Prefer。作为替代,服务器可以在响应中包含特殊值 "*" 的 Vary 首部(参见 [RFC7231] 第 8.2.1 节)。但请注意,使用 "Vary: *" 会使代理无法缓存该响应。
注意,虽然偏好标记在结构上类似于 HTTP Expect 标记,但 Prefer 与 Expect 首部用于完全不同的目的,偏好不能作为期望(expectations)使用。
2.1. 示例
下面的示例演示了本规范定义的各种偏好,以及为说明目的所示的未定义扩展:
1. 如果请求在 10 秒内无法处理完毕,则为异步处理返回 202 (Accepted)。另外示例中也指明了未定义的 "priority" 偏好:
POST /some-resource HTTP/1.1
Host: example.org
Content-Type: text/plain
Prefer: respond-async, wait=10
Prefer: priority=5
{...}
2. 使用宽容(lenient)处理:
POST /some-resource HTTP/1.1
Host: example.org
Content-Type: text/plain
Prefer: Lenient
{...}
3. 在 return=minimal 偏好上使用一个可选的未定义参数:
POST /some-resource HTTP/1.1
Host: example.org
Content-Type: text/plain
Prefer: return=minimal; foo="some parameter"
{...}
3. Preference‑Applied 响应首部字段
Preference‑Applied 响应首部可包含在响应消息中,用来指示服务器在处理请求时采纳并应用了哪些 Prefer 标记。
ABNF:
Preference-Applied = "Preference-Applied" ":" 1#applied-pref
applied-pref = token [ BWS "=" BWS word ]
Preference‑Applied 首部的语法与 Prefer 不同之处在于它不包含参数。
仅在服务器是否应用了特定偏好不明显且这种歧义可能影响客户端对响应的处理时,才有必要使用 Preference‑Applied 首部。例如,当使用 "return=representation" 或 "return=minimal" 偏好时,客户端可能无法仅通过检查响应负载可靠地判断偏好是否被应用。在这种情况下,可以使用 Preference‑Applied 首部字段。
请求:
PATCH /my-document HTTP/1.1
Host: example.org
Content-Type: application/example-patch
Prefer: return=representation
[{"op": "add", "path": "/a", "value": 1}]
响应:
HTTP/1.1 200 OK
Content-Type: application/json
Preference-Applied: return=representation
Content-Location: /my-document
{"a": 1}
4. 偏好定义
下面的小节定义了一组初始偏好。可以注册其它偏好以便于复用或促进其他应用的使用。本规范在 IANA 下建立了一个偏好注册表(见 第 5.1 节)。
4.1. “respond-async” 偏好
“respond-async” 偏好指示客户端偏好服务器以异步方式响应。例如,当生成响应所需的时间超过服务器设定的某个阈值时,服务器可以通过返回 202 (Accepted) 响应来采纳该偏好。
ABNF:
respond-async = "respond-async"
“respond-async” 偏好的主要动机是通过允许客户端向服务器表明其支持并偏好异步响应,来促进异步请求处理的运作。
示例:在请求中指定 "respond-async" 偏好:
POST /collection HTTP/1.1
Host: example.org
Content-Type: text/plain
Prefer: respond-async
{Data}
示例:返回 202 (Accepted) 的异步响应:
HTTP/1.1 202 Accepted Location: http://example.org/collection/123
尽管 202 (Accepted) 状态由 [RFC7231] 定义,但关于如何使用该状态码以及如何确定操作最终结果的过程未给出详细指导。因此,服务器是否以及如何支持异步响应是实现细节,不在本规范范围之内。
4.2. “return=representation” 与 “return=minimal” 偏好
“return=representation” 偏好表示客户端偏好服务器在成功响应中包含表示资源当前状态的实体。
另一方面,“return=minimal” 偏好表示客户端希望服务器在成功响应中仅返回最小响应。通常这样的响应会使用 204 (No Content) 状态,但也可以使用其他合适的状态(例如 200 (OK) 且响应实体长度为零)。什么构成适当的最小响应完全由服务器决定。
ABNF:
return = "return" BWS "=" BWS ("representation" / "minimal")
当采纳 "return=representation" 偏好时,返回的表示在请求影响另一个资源时可能并非对有效请求 URI 的表示。在这种情况下,可使用 Content-Location 首部来标识返回表示的 URI。
“return=representation” 偏好旨在通过消除随后为检索修改后资源当前表示而进行的 GET 请求来优化客户端与服务器之间的通信。
在成功处理诸如 POST 或 PUT 之类的修改请求后,服务器可以选择返回描述操作状态的实体,或返回修改后资源的表示。返回哪种类型的实体(如果返回)完全由服务器决定,但 “return=representation” 和 “return=minimal” 偏好允许服务器在构建响应时考虑客户端的偏好。
示例:在请求中指定 "return=representation" 偏好:
PATCH /item/123 HTTP/1.1 Host: example.org Content-Type: application/example-patch Prefer: return=representation 1c1 < ABCDEFGHIJKLMNOPQRSTUVWXYZ --- > BCDFGHJKLMNPQRSTVWXYZ
示例响应:包含资源表示:
HTTP/1.1 200 OK Content-Location: http://example.org/item/123 Content-Type: text/plain ETag: "d3b07384d113edec49eaa6238ad5ff00" BCDFGHJKLMNPQRSTVWXYZ
相比之下,"return=minimal" 偏好可以减少服务器在请求后需要返回的数据量。这在与带宽受限的移动设备通信或客户端仅需知道请求是否成功而无需进一步信息时尤其有用。
示例:在请求中指定 "return=minimal" 偏好:
POST /collection HTTP/1.1
Host: example.org
Content-Type: text/plain
Prefer: return=minimal
{Data}
示例最小响应:
HTTP/1.1 201 Created Location: http://example.org/collection/123
"return=minimal" 与 "return=representation" 是互斥的指令。预计不会出现某个请求同时包含两者的合理情形。任何同时包含两者的请求很可能是客户端编码错误的结果,因此可以按未指定任何偏好来处理。
4.3. “wait” 偏好
“wait” 偏好可用于指定客户端期望服务器从接收请求到生成响应所花费时间的上限(以秒为单位)。如果生成响应所需时间超过指定时间,服务器或代理可以选择采用异步处理模型,例如返回 202 (Accepted)。
ABNF:
wait = "wait" BWS "=" BWS delta-seconds
需要注意的是,HTTP 消息在网络传输和经由中间件处理时也会花费时间。这会使客户端等待响应的总体时间增加,超出服务器自身处理请求所需的时间。具有严格时限要求的客户端可以估计这些因素并相应地调整 wait 值。
与其他偏好一样,“wait” 偏好也可以被忽略。客户端可以放弃那些超出其愿意等待时间的请求。
例如,服务器收到如下请求时,如果处理该请求需要超过 10 秒,则可能选择异步响应:
POST /collection HTTP/1.1
Host: example.org
Content-Type: text/plain
Prefer: respond-async, wait=10
{Data}
4.4. “handling=strict” 与 “handling=lenient” 处理偏好
“handling=strict” 与 “handling=lenient” 偏好指示客户端希望服务器如何处理在请求处理过程中可能出现的错误情况。例如,如果请求负载包含若干小的语法或语义错误,但服务器仍能理解并成功处理请求,则必须决定是以适当的 4xx 错误码拒绝请求,还是继续处理。使用 "handling=strict" 偏好可以指示客户端希望服务器拒绝请求(即使某个错误可能是可恢复的)。相反,"handling=lenient" 表示客户端希望服务器尝试处理请求。
ABNF:
handling = "handling" BWS "=" BWS ("strict" / "lenient")
示例:在请求中指定 "strict" 偏好:
POST /collection HTTP/1.1 Host: example.org Content-Type: text/plain Prefer: handling=strict
"handling=strict" 与 "handling=lenient" 为互斥指令。预计不会有使两者同时出现在单个请求中有意义的情况。任何同时包含两者的请求很可能是客户端的编码错误,因此可按未指定任何偏好来处理。
5. IANA 注意事项
“Prefer” 与 “Preference-Applied” 首部字段已被添加到 [RFC3864] 定义的 “Permanent Message Header Field Names” 注册表(http://www.iana.org/assignments/message-headers)。
- 首部字段名:Prefer
- 适用协议:HTTP
- 状态:Standard
- 作者:James M Snell <jasnell@gmail.com>
- 变更控制者:IETF
- 规范文档:本规范,第 第 2 节
- 首部字段名:Preference-Applied
- 适用协议:HTTP
- 状态:Standard
- 作者:James M Snell <jasnell@gmail.com>
- 变更控制者:IETF
- 规范文档:本规范,第 第 3 节
5.1. 偏好注册表
IANA 已在 “Hypertext Transfer Protocol (HTTP) Parameters” 注册表下创建了一个新的注册表 “HTTP Preferences”。新的注册使用 Specification Required 策略 [RFC5226]。偏好的注册要求在 第 4 节 中描述。
注册请求包括下面的注册模板,通常在所需规范中发布。然而,为了在发布之前分配值,指定专家可以在确认规范会被发布后基于单独提交的模板批准注册。在专家认为未及时注册但已被广泛部署且不太可能及时注册的未注册偏好时,第三方也可以提交注册请求。
注册模板如下:
- Preference:(Prefer 请求首部字段中符合 第 2 节 所给语法规则的值)
- Value:(对偏好标记可能值的枚举或描述)
- Optional Parameters:(偏好标记相关的可选参数及其值的枚举)
- Description:
- Reference:
- Notes: [可选]
若特定偏好标记定义中不包含“Value”或“Optional Parameters”字段,则在注册模板中可以省略这些字段。
注册请求应发送至 <ietf-http-wg@w3.org> 邮件列表,并在主题行中清楚标注(例如,“NEW PREFERENCE - example” 用于注册 "example" 偏好)。指定专家将在最多 14 天内批准或拒绝注册请求,并将决定告知审查列表和 IANA。拒绝应包含解释并在适用时建议如何使请求成功。
5.2. 初始注册表内容
“HTTP Preferences” 注册表的初始内容如下:
- Preference: respond-async
- Description: 指示客户端偏好服务器对请求以异步方式响应。
- Reference: [本规范], 第 4.1 节
- Preference: return
- Value: "minimal" 或 "representation" 其一
- Description: 当值为 "minimal" 时,表示客户端偏好服务器对请求返回最小响应;当值为 "representation" 时,表示客户端偏好服务器在响应中包含资源当前状态的表示。
- Reference: [本规范], 第 4.2 节
- Preference: wait
- Description: 指示客户端期望服务器在接收请求后处理请求所需时间的上限。
- Reference: [本规范], 第 4.3 节
- Preference: handling
- Value: "strict" 或 "lenient" 其一
- Description: 值为 "strict" 表示客户端希望服务器对请求的处理应用严格的验证和错误处理;值为 "lenient" 表示客户端希望服务器应用宽容的验证和错误处理。
- Reference: [本规范], 第 4.4 节
6. 安全注意事项
客户端请求的具体偏好可能引入超出 HTTP/1.1(及其关联规范)中讨论的安全注意事项之外的安全问题。实现者需要参考每个偏好的规范与描述,以确定与之相关的安全注意事项。
服务器在尝试遵从某个偏好时可能承担更高的成本(例如返回原本不会包含表示的响应时所需的代价;或为异步响应追踪状态所需的资源承诺)。服务器无条件地遵从偏好可能被利用进行拒绝服务攻击。服务器可以忽略所表达的偏好以避免消耗其不愿投入的资源。
7. 参考文献
7.1. 规范性参考文献
- [RFC2119]
- Bradner, S., “Key words for use in RFCs to Indicate Requirement Levels”, BCP 14, RFC 2119, March 1997, <http://www.rfc-editor.org/info/rfc2119>.
- [RFC3864]
- Klyne, G., Nottingham, M., and J. Mogul, “Registration Procedures for Message Header Fields”, BCP 90, RFC 3864, September 2004, <https://www.rfc-editor.org/info/rfc3864>.
- [RFC5226]
- Narten, T. and H. Alvestrand, “Guidelines for Writing an IANA Considerations Section in RFCs”, RFC 5226, May 2008, <https://www.rfc-editor.org/info/rfc5226>.
- [RFC5234]
- Crocker, D., Ed. and P. Overell, “Augmented BNF for Syntax Specifications: ABNF”, STD 68, RFC 5234, January 2008, <https://www.rfc-editor.org/info/rfc5234>.
- [RFC7230]
- Fielding, R., Ed. and J. Reschke, Ed., “Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing”, RFC 7230, June 2014.
- [RFC7231]
- Fielding, R., Ed. and J. Reschke, Ed., “Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content”, RFC 7231, June 2014.
7.2. 补充性参考文献
- [RFC5023]
- Gregorio, J., Ed. and B. de hOra, Ed., “The Atom Publishing Protocol”, RFC 5023, October 2007, <https://www.rfc-editor.org/info/rfc5023>.