5. 请求头部字段
客户端发送请求头部字段, 用于提供有关请求上下文的更多信息, 根据目标资源状态使请求成为条件式请求, 建议响应的首选格式, 提供认证凭据, 或修改预期的请求处理. 这些字段充当请求修改器, 类似于编程语言方法调用中的参数.
5.1. 控制
控制是指引请求特定处理的请求头部字段.
5.1.1. Expect
请求中的 Expect 头部字段指示服务器为了正确处理此请求而需要支持的一组特定行为 (期望). 本规范定义的唯一此类期望是 100-continue.
Expect = "100-continue"
Expect 字段值不区分大小写.
收到不同于 100-continue 的 Expect 字段值的服务器, 可以用 417 (Expectation Failed) 状态码响应, 以指示无法满足意外的期望.
100-continue 期望告知接收者, 客户端即将在此请求中发送一个 (可能很大的) 消息体, 并希望在方法、目标 URI 和头部字段不足以立即导致成功、重定向或错误响应时, 收到 100 (Continue) 临时响应. 这允许客户端在实际发送消息体之前等待一个值得发送消息体的指示, 当消息体很大或客户端预计很可能出现错误时 (例如首次发送改变状态的方法, 且此前没有已验证的认证凭据), 可以提高效率.
例如:
Expect: 100-continue
发送 100-continue 期望的客户端不需要等待任何特定时长; 即使尚未收到响应, 这样的客户端 MAY 继续发送消息体. 此外, 由于 100 (Continue) 响应不能通过 HTTP/1.0 中间方发送, 这样的客户端 SHOULD NOT 在发送消息体之前无限期等待.
客户端要求:
- 客户端 MUST NOT 在不包含消息体的请求中生成 100-continue 期望.
服务器要求:
- 收到 HTTP/1.0 请求中的 100-continue 期望的服务器 MUST 忽略该期望.
- 如果服务器已经收到对应请求的部分或全部消息体, 或者分帧表明不存在消息体, 服务器 MAY 省略发送 100 (Continue) 响应.
- 发送 100 (Continue) 响应的服务器 MUST 在收到并处理消息体后最终发送一个最终状态码, 除非连接过早关闭.
- 在读取完整消息体之前以最终状态码响应的服务器 SHOULD 在该响应中指明它打算关闭连接, 还是继续读取并丢弃请求消息 (见 [RFC7230] Section 6.6).
5.1.2. Max-Forwards
Max-Forwards 头部字段为 TRACE (Section 4.3.8) 和 OPTIONS (Section 4.3.7) 请求方法提供一种机制, 用于限制请求被代理转发的次数. 当客户端试图追踪一个看起来在链路中途失败或循环的请求时, 这可能很有用.
Max-Forwards = 1*DIGIT
Max-Forwards 值是一个十进制整数, 指示此请求消息还能被转发的剩余次数.
每个收到包含 Max-Forwards 头部字段的 TRACE 或 OPTIONS 请求的中间方, 在转发请求之前 MUST 检查并更新其值. 如果收到的值为零 (0), 中间方 MUST NOT 转发该请求; 相反, 中间方 MUST 作为最终接收者响应. 如果收到的 Max-Forwards 值大于零, 中间方 MUST 在转发消息中生成更新后的 Max-Forwards 字段, 其字段值为 a) 收到的值减一 (1) 或 b) 接收者支持的最大值二者中的较小者.
接收者 MAY 忽略与任何其他请求方法一起收到的 Max-Forwards 头部字段.
示例:
Max-Forwards: 10
5.2. 条件式请求
HTTP 条件请求头部字段 [RFC7232] 允许客户端对目标资源状态设置前置条件, 使得当该前置条件求值为假时, 与方法语义对应的动作不会被应用. 本规范定义的每个前置条件都由一组从目标资源先前表示获得的验证器与选定表示当前验证器状态之间的比较组成 ([RFC7232] Section 7.2). 因此, 这些前置条件会评估自客户端已知的给定状态以来目标资源状态是否已改变. 这种评估的效果取决于方法语义和所选条件, 如 [RFC7232] Section 5 所定义.
5.3. 内容协商
用户代理可以发送以下请求头部字段, 以参与 Section 3.4.1 中定义的响应内容主动协商. 这些字段中发送的偏好适用于响应中的任何内容, 包括目标资源的表示、错误或处理状态的表示, 甚至可能包括协议中出现的各种文本字符串.
5.3.1. 质量值
许多用于主动协商的请求头部字段使用一个名为 "q" (不区分大小写) 的通用参数, 为关联内容类型的偏好分配相对"权重". 该权重称为"质量值" (quality value, 或 "qvalue"), 因为服务器配置中常使用同一参数名为可为资源选择的各种表示质量分配权重.
该权重被规范化为 0 到 1 范围内的实数, 其中 0.001 表示最低偏好, 1 表示最高偏好; 值 0 表示 "not acceptable". 如果不存在 "q" 参数, 默认权重为 1.
weight = OWS ";" OWS "q=" qvalue
qvalue = ( "0" [ "." 0*3DIGIT ] )
/ ( "1" [ "." 0*3("0") ] )
qvalue 的发送者 MUST NOT 在小数点后生成超过三位数字. 用户对此类值的配置也应以同样方式限制.
示例:
Accept: text/html;q=1, application/json;q=0.8
Accept-Language: en-US;q=0.9, fr;q=0.7
5.3.2. Accept
用户代理可以使用 Accept 头部字段指定可接受的响应媒体类型. Accept 头部字段可用于指示请求被明确限制为少量期望类型, 例如请求内联图像时.
Accept = #( media-range [ accept-params ] )
media-range = ( "*/*"
/ ( type "/" "*" )
/ ( type "/" subtype )
) *( OWS ";" OWS parameter )
accept-params = weight *( accept-ext )
accept-ext = OWS ";" OWS token [ "=" ( token / quoted-string ) ]
星号 "" 字符用于把媒体类型分组成范围, 其中 "/" 表示所有媒体类型, "type/" 表示该类型的所有子类型. media-range 可以包含适用于该范围的媒体类型参数.
每个 media-range 后面可以跟随零个或多个适用的媒体类型参数 (例如 charset)、一个可选的用于指示相对权重的 "q" 参数 (Section 5.3.1), 然后是零个或多个扩展参数. 如果存在任何扩展 (accept-ext), 则必须有 "q" 参数, 以免它们被误认为媒体类型参数.
示例
Accept: audio/*; q=0.2, audio/basic
解释为: "我更偏好 audio/basic, 但如果经过 80% 的质量折减后任何 audio 类型仍是最佳可用类型, 就发送它."
一个更详细的示例是
Accept: text/plain; q=0.5, text/html,
text/x-dvi; q=0.8, text/x-c
用文字表达, 可解释为: "text/html 和 text/x-c 是同等首选的媒体类型, 但如果它们不存在, 就发送 text/x-dvi 表示; 如果它也不存在, 就发送 text/plain 表示."
媒体范围可以被更具体的媒体范围或具体媒体类型覆盖. 如果多个媒体范围适用于给定类型, 最具体的引用优先. 例如,
Accept: text/*, text/plain, text/plain;format=flowed, */*
具有以下优先级:
- text/plain;format=flowed
- text/plain
- text/*
- /
与给定类型关联的媒体类型质量因子, 通过查找与该类型匹配且优先级最高的媒体范围来确定. 例如,
Accept: text/*;q=0.3, text/html;q=0.7, text/html;level=1,
text/html;level=2;q=0.4, */*;q=0.5
会关联以下值:
| Media Type | Quality Value |
|---|---|
| text/html;level=1 | 1 |
| text/html | 0.7 |
| text/plain | 0.3 |
| image/jpeg | 0.5 |
| text/html;level=2 | 0.4 |
| text/html;level=3 | 0.7 |
注意: 用户代理可能会为某些媒体范围提供一组默认质量值. 但是, 除非用户代理是不能与其他渲染代理交互的封闭系统, 否则这组默认值应可由用户配置.
5.3.3. Accept-Charset
用户代理可以发送 Accept-Charset 头部字段, 以指示文本响应内容中可接受的 charset. 该字段允许能够理解更全面或专用 charset 的用户代理, 向能够用这些 charset 表示信息的源服务器表明这种能力.
Accept-Charset = 1#( ( charset / "*" ) [ weight ] )
Charset 名称定义于 Section 3.1.1.2. 用户代理 MAY 为每个 charset 关联一个质量值, 以指示用户对该 charset 的相对偏好, 如 Section 5.3.1 所定义. 示例为
Accept-Charset: iso-8859-5, unicode-1-1;q=0.8
特殊值 "" 如果出现在 Accept-Charset 字段中, 将匹配 Accept-Charset 字段中未在其他位置提及的每个 charset. 如果 Accept-Charset 字段中不存在 "", 则字段中未明确提及的任何 charset 都被客户端视为 "not acceptable".
不带任何 Accept-Charset 头部字段的请求意味着用户代理将在响应中接受任何 charset. 大多数通用用户代理不会发送 Accept-Charset, 除非被专门配置为这样做, 因为详细列出支持的 charset 会让服务器更容易凭借异常的 (本地化) 偏好识别个人.
如果请求中存在 Accept-Charset 头部字段, 且响应的可用表示中没有任何表示具有被列为可接受的 charset, 源服务器可以遵循该头部字段并发送 406 (Not Acceptable) 响应, 或者忽略该头部字段, 将资源视为不受内容协商约束.
5.3.4. Accept-Encoding
用户代理可以使用 Accept-Encoding 头部字段指示响应中可接受的响应内容编码 (Section 3.1.2.1). "identity" 令牌用作"无编码"的同义词, 以表达不偏好任何编码的情况.
Accept-Encoding = #( codings [ weight ] )
codings = content-coding / "identity" / "*"
每个 codings 值 MAY 给出一个关联质量值 (权重), 表示对该编码的偏好, 如 Section 5.3.1 所定义. Accept-Encoding 字段中的星号 "*" 符号匹配头部字段中未明确列出的任何可用 content-coding.
示例:
Accept-Encoding: compress, gzip
Accept-Encoding:
Accept-Encoding: *
Accept-Encoding: compress;q=0.5, gzip;q=1.0
Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0
不带 Accept-Encoding 头部字段的请求意味着用户代理对 content-codings 没有偏好. 虽然这允许服务器在响应中使用任何 content-coding, 但并不意味着用户代理能够正确处理所有编码.
服务器使用以下规则测试给定表示的 content-coding 是否可接受:
-
如果请求中没有
Accept-Encoding字段, 用户代理认为任何 content-coding 都可接受. -
如果表示没有 content-coding, 则默认可接受, 除非
Accept-Encoding字段通过声明 "identity;q=0" 或在没有针对 "identity" 的更具体条目时声明 "*;q=0" 明确排除它. -
如果表示的 content-coding 是
Accept-Encoding字段中列出的 content-codings 之一, 则它可接受, 除非伴随 qvalue 为 0. (如 Section 5.3.1 所定义, qvalue 为 0 表示 "not acceptable".) -
如果多个 content-codings 可接受, 则首选具有最高非零 qvalue 的可接受 content-coding.
组合字段值为空的 Accept-Encoding 头部字段意味着用户代理不希望响应中有任何 content-coding. 如果请求中存在 Accept-Encoding 头部字段, 且响应的可用表示中没有任何表示具有被列为可接受的 content-coding, 源服务器 SHOULD 发送不带任何 content-coding 的响应.
注意: 大多数 HTTP/1.0 应用程序不识别或遵守与 content-codings 关联的 qvalues. 这意味着 qvalues 可能不起作用, 且不允许与 x-gzip 或 x-compress 一起使用.
5.3.5. Accept-Language
用户代理可以使用 Accept-Language 头部字段指示响应中首选的一组自然语言. 语言标签定义于 Section 3.1.3.1.
Accept-Language = 1#( language-range [ weight ] )
language-range =
<language-range, see [RFC4647], Section 2.1>
每个 language-range 都可以给出一个关联质量值, 表示对该范围所指定语言的用户偏好的估计, 如 Section 5.3.1 所定义. 例如,
Accept-Language: da, en-gb;q=0.8, en;q=0.7
表示: "我更偏好丹麦语, 但会接受英国英语和其他类型的英语."
不带任何 Accept-Language 头部字段的请求意味着用户代理将在响应中接受任何语言. 如果请求中存在该头部字段, 且响应的可用表示中没有任何表示具有匹配的语言标签, 源服务器可以忽略该头部字段, 将资源视为不受内容协商约束; 或者遵循该头部字段并发送 406 (Not Acceptable) 响应. 不过, 不鼓励后者, 因为这样可能阻止用户访问他们或许能够使用的内容 (例如借助翻译软件).
注意, 一些接收者会把语言标签列出的顺序视为优先级递减的指示, 尤其是对于分配了相同质量值的标签 (没有值等同于 q=1). 但是, 不能依赖这种行为. 为保持一致并最大化互操作性, 许多用户代理会为每个语言标签分配唯一质量值.
关于语言优先级列表的更多讨论见 [RFC4647] Section 2.3.
5.4. 认证凭据
两个头部字段用于携带认证凭据, 如 HTTP Authentication [RFC7235] 中所定义. 注意, 各种用于用户认证的自定义机制会使用 Cookie 头部字段实现此目的, 如 [RFC6265] 所定义.
5.4.1. Authorization
Authorization 头部字段允许用户代理向源服务器认证自身 -- 通常但不一定是在收到 401 (Unauthorized) 响应之后. 其值由凭据组成, 这些凭据包含用户代理针对所请求资源 realm 的认证信息.
Authorization = credentials
如果请求已认证且指定了 realm, 则假定同一凭据对该 realm 内的所有其他请求有效 (前提是认证方案本身没有其他要求, 例如凭据随 challenge 值变化或使用同步时钟).
转发请求的代理 MUST NOT 修改该请求中的任何 Authorization 字段. 详情见 [RFC7235] Section 3.2.
用户代理若要发送包含密码的凭据, 必须知道到源服务器的连接是安全的. 相关安全考虑事项见 Section 9.4.
5.4.2. Proxy-Authorization
Proxy-Authorization 头部字段允许客户端向需要认证的代理标识自身 (或其用户). 其值由凭据组成, 这些凭据包含客户端针对所请求资源的代理和/或 realm 的认证信息.
Proxy-Authorization = credentials
不同于 Authorization, Proxy-Authorization 头部字段只适用于使用 Proxy-Authenticate 字段要求认证的下一个入站代理. 当链中使用多个代理时, Proxy-Authorization 头部字段由第一个期望接收凭据的入站代理消费. 如果这是代理之间协作认证给定请求的机制, 代理 MAY 将客户端请求中的凭据中继给下一个代理.
5.5. 请求上下文
以下请求头部字段提供有关请求上下文的附加信息, 包括有关用户、用户代理以及请求背后资源的信息.
5.5.1. From
From 头部字段包含控制发出请求的用户代理的人类用户的 Internet 电子邮件地址. 该地址应按 [RFC5322] Section 3.4 中 "mailbox" 的定义, 可供机器使用.
From = mailbox
示例为:
From: [email protected]
From 头部字段很少由非机器人用户代理发送. 用户代理 SHOULD NOT 在未经用户显式配置的情况下发送 From 头部字段, 因为这可能与用户隐私利益或其站点安全策略冲突.
机器人用户代理 SHOULD 发送有效的 From 头部字段, 以便当服务器出现问题时 (例如机器人正在发送过多、不想要或无效的请求), 可以联系到负责运行该机器人的人员.
服务器 SHOULD NOT 使用 From 头部字段进行访问控制或认证, 因为大多数接收者会假定该字段值是公开信息.
5.5.2. Referer
Referer [sic] 头部字段允许用户代理指定一个 URI 引用, 该引用指向获取目标 URI 的资源 (即 "referrer", 尽管字段名拼写错误). 用户代理在生成 Referer 字段值时, MUST NOT 包含 URI 引用 [RFC3986] 的 fragment 和 userinfo 组件 (如果有).
Referer = absolute-URI / partial-URI
Referer 头部字段允许服务器为简单分析、日志记录、优化缓存等目的生成指向其他资源的反向链接. 它还允许发现过时或拼写错误的链接以便维护. 一些服务器使用 Referer 头部字段作为拒绝来自其他站点链接 (所谓 "deep linking") 或限制跨站请求伪造 (CSRF) 的手段, 但并非所有请求都包含它.
示例:
Referer: http://www.example.org/hypertext/Overview.html
如果目标 URI 是从没有自身 URI 的来源获得的 (例如用户键盘输入, 或用户书签/收藏夹中的条目), 用户代理 MUST 要么排除 Referer 字段, 要么以值 "about:blank" 发送它.
Referer 字段可能泄露有关请求上下文或用户浏览历史的信息. 如果引用资源的标识符泄露个人信息 (如账户名) 或本应保密的资源 (如防火墙后或安全服务内部的资源), 这就是隐私问题. 大多数通用用户代理在引用资源是本地 "file" 或 "data" URI 时不会发送 Referer 头部字段. 如果引用页面是通过安全协议接收的, 用户代理 MUST NOT 在不安全的 HTTP 请求中发送 Referer 头部字段. 其他安全考虑事项见 Section 9.4.
已知一些中间方会不加区分地从出站请求中移除 Referer 头部字段. 这会产生不幸的副作用, 干扰对 CSRF 攻击的防护, 而 CSRF 对其用户的危害可能大得多. 希望限制 Referer 中信息披露的中间方和用户代理扩展, 应将其更改限制为特定编辑, 例如用假名替换内部域名, 或截断 query 和/或 path 组件. 当字段值与请求目标共享相同 scheme 和 host 时, 中间方 SHOULD NOT 修改或删除 Referer 头部字段.
5.5.3. TE
TE 头部字段指示除 chunked 之外, 客户端愿意在响应中接受哪些传输编码, 以及客户端是否愿意在 chunked 传输编码中接受 trailer 字段.
TE 字段值由逗号分隔的传输编码名称列表组成, 每个名称允许可选参数 (如 [RFC7230] Section 4 所述), 和/或关键字 "trailers".
TE = #( t-codings )
t-codings = "trailers" / ( transfer-coding [ t-ranking ] )
t-ranking = OWS ";" OWS "q=" rank
rank = ( "0" [ "." 0*3DIGIT ] )
/ ( "1" [ "." 0*3("0") ] )
以下是三个 TE 使用示例.
TE: deflate
TE:
TE: trailers, deflate;q=0.5
TE 头部字段只适用于直接连接. 因此, 只要 HTTP/1.1 消息中存在 TE, 关键字 "TE" 就 MUST 在 Connection 头部字段中提供 ([RFC7230] Section 6.1).
服务器使用与 Accept-Encoding (Section 5.3.4) 相同的规则测试传输编码是否可接受, 但名为 "trailers" 的编码总是可接受, 且 "q" 参数值为 0 的传输编码不可接受.
由于 TE 头部字段只适用于直接连接, TE 的发送者 MUST 还在 Connection 头部字段中发送 "TE" 连接选项 ([RFC7230] Section 6.1), 以防不支持其语义的中间方转发 TE 字段.
5.5.4. User-Agent
User-Agent 头部字段包含有关发起请求的用户代理的信息. 服务器常使用这些信息帮助识别报告的互操作性问题范围, 绕过或调整响应以避免特定用户代理限制, 以及分析浏览器或操作系统使用情况. 用户代理 SHOULD 在每个请求中发送 User-Agent 字段, 除非被专门配置为不这样做.
User-Agent = product *( RWS ( product / comment ) )
User-Agent 字段值由一个或多个产品标识符组成, 每个标识符后跟零个或多个注释 ([RFC7230] Section 3.2), 它们共同标识用户代理软件及其重要子产品. 按约定, 产品标识符按其对识别用户代理软件的重要性递减列出. 每个产品标识符由名称和可选版本组成, 如 [RFC7230] Section 5.5.3 所定义.
示例:
User-Agent: CERN-LineMode/2.15 libwww/2.17b3
用户代理 SHOULD NOT 生成包含不必要细粒度细节的 User-Agent 字段, 并 SHOULD 限制第三方添加子产品. 过长且过于详细的 User-Agent 字段值会增加请求延迟, 并增加用户违背自身意愿被识别的风险 ("fingerprinting").
同样, 鼓励实现不要使用其他实现的 product token 来声明与其兼容, 因为这规避了该字段的目的. 如果用户代理伪装成不同的用户代理, 接收者可以假定用户有意希望看到为该被标识用户代理定制的响应, 即使这些响应对实际使用的用户代理可能工作得不那么好.