跳到主要内容

2. ORIGIN HTTP/2 帧 (The ORIGIN HTTP/2 Frame)

本文档定义一种新的 HTTP/2 帧类型 ([RFC7540] 第 4 节), 名为 ORIGIN. 该帧允许服务器指示它希望客户端将哪些 origin [RFC6454] 视为该帧所在连接的 Origin Set (第 2.3 节) 成员.

2.1. 语法

ORIGIN 帧类型为 0xc (十进制 12), 包含零个或多个 Origin-Entry 字段实例.

+-------------------------------+-------------------------------+
| Origin-Entry (*) ...
+-------------------------------+-------------------------------+

Origin-Entry 是一个以长度分隔的字符串:

+-------------------------------+-------------------------------+
| Origin-Len (16) | ASCII-Origin? ...
+-------------------------------+-------------------------------+

具体如下:

Origin-Len: 一个无符号 16 bit 整数, 指示 ASCII-Origin 字段的长度, 单位为 octets.

Origin: 一个可选字符序列, 包含某个 origin ([RFC6454] 第 6.2 节) 的 ASCII 序列化形式. 发送方声明该连接现在或将来可以对该 origin 具有权威性.

ORIGIN 帧不定义任何 flags. 但是, 本规范未来的更新可以定义 flags. 见第 2.2 节.

2.2. 处理 ORIGIN 帧

ORIGIN 帧是 HTTP/2 的非关键扩展. 不支持该帧的端点收到它时可以安全忽略.

实现该规范的客户端收到 ORIGIN 帧后, 会使用它初始化和操作 Origin Set (见第 2.3 节), 从而改变客户端为 origin servers 建立权威性的方式 (见第 2.4 节).

ORIGIN 帧MUST在 stream 0 上发送. 任何其他 stream 上的 ORIGIN 帧都是无效的, MUST被忽略.

同样, ORIGIN 帧仅在带有 "h2" 协议标识符的连接上有效, 或在协议定义明确指定时有效. 当在带有 "h2c" 协议标识符的连接上收到 ORIGIN 帧时, MUST忽略该帧.

本规范没有为 ORIGIN 帧定义任何 flags, 但本规范未来的更新可以通过 IETF consensus 使用它们来改变其语义. 前四个 flags (0x1, 0x2, 0x4 和 0x8) 保留用于向后不兼容的变更. 因此, 当其中任何一个被设置时, 除非理解该 flag 的语义, 符合本规范的客户端MUST忽略包含这些 flags 的 ORIGIN 帧. 其余 flags 保留用于向后兼容的变更, 不影响符合本规范的客户端的处理.

ORIGIN 帧描述连接的属性, 因此按逐跳方式处理. 中间节点MUST NOT转发 ORIGIN 帧. 配置为使用代理的客户端MUST忽略从该代理收到的任何 ORIGIN 帧.

帧负载中的每个 ASCII-Origin 字段都MUST按 origin ([RFC6454] 第 6.2 节) 的 ASCII 序列化形式解析. 如果解析失败, 则MUST忽略该字段.

请注意, ORIGIN 帧在 Origin-Entry 中不支持通配符名称, 例如 "*.example.com". 因此, 当使用通配符证书时发送 ORIGIN, 实际上会禁用 ORIGIN 帧中未显式列出的任何 origins, 前提是客户端理解 ORIGIN.

有关处理 ORIGIN 帧的示例算法, 见附录 A.

2.3. Origin Set

给定连接可能用于的一组 origins (依据 [RFC6454]) 在本规范中称为 Origin Set.

默认情况下, 连接的 Origin Set 未初始化. 未初始化的 Origin Set 表示客户端应用 [RFC7540] 第 9.1.1 节中的 coalescing rules.

客户端首次收到并成功处理 ORIGIN 帧后, 该连接的 Origin Set 被定义为包含一个 initial origin. initial origin 由以下内容组成:

  • Scheme: "https"
  • Host: Server Name Indication (SNI) ([RFC6066] 第 3 节) 中发送的值, 转换为小写. 如果不存在 SNI, 则使用连接的远端地址, 即服务器的 IP 地址
  • Port: 连接的远端端口, 即服务器端口

该 ORIGIN 帧以及后续 ORIGIN 帧的内容允许服务器按第 2.2 节所述, 逐步向 Origin Set 添加新的 origins.

Origin Set 也会受 421 (Misdirected Request) 响应状态码影响, 其定义见 [RFC7540] 第 9.1.2 节. 收到带有该状态码的响应后, 实现本规范的客户端MUST创建对应请求 origin 的 ASCII 序列化形式 (依据 [RFC6454] 第 6.2 节), 并在该 origin 存在于连接的 Origin Set 中时将其移除.

注意: 当向作为 alternative service [RFC7838] 初始化的连接发送 ORIGIN 帧时, initial Origin Set (第 2.3 节) 将包含具有适当 scheme 和 hostname 的 origin, 因为 RFC 7838 规定在 SNI 中发送 origin 的 hostname. 但是, 端口可能不同于预期 origin 的端口, 因为 initial Origin Set 使用实际正在使用的端口计算, 而 alternative service 可以使用不同端口. 在这种情况下, 需要在 ORIGIN 帧中显式发送预期 origin.

例如, 某客户端为 "https://example.com" 发起请求, 并被定向到 ("h2", "x.example.net", "8443") 上的 alternative service. 如果该 alternative service 发送 ORIGIN 帧, initial origin 将是 "https://example.com:8443". 除非该 origin 被显式包含在 ORIGIN 帧中, 否则客户端无法使用该 alternative service 为 "https://example.com" 发起请求.

2.4. 使用 ORIGIN 处理权威性, Push 和 Coalescing

[RFC7540] 第 10.1 节同时使用 DNS 和所呈现的 Transport Layer Security (TLS) 证书来建立某连接对哪些 origin server 具有权威性, 这与 [RFC7230] 中 HTTP/1.1 的做法相同.

此外, [RFC7540] 第 9.1.1 节明确允许连接用于多个 origin server, 前提是它对这些 origin 具有权威性. 这会影响哪些响应可以被视为权威响应, 包括对请求的直接响应以及 server push (见 [RFC7540] 第 8.2.2 节). 间接地, 这也会影响哪些请求会在某连接上发送, 因为客户端通常只会在它认为对相关 origin 具有权威性的连接上发送请求.

一旦连接的 Origin Set 已初始化, 实现本规范的客户端就使用它帮助确定该连接对哪些对象具有权威性. 具体而言, 这类客户端MUST NOT将连接视为对不在 Origin Set 中的 origin 具有权威性, 并且对于 Origin Set 中该连接具有权威性的所有 origins, 客户端SHOULD使用该连接发送所有请求, 除非存在打开新连接的运行原因.

请注意, 要将某连接视为对给定 origin 具有权威性, 服务器仍需要使用通过适当检查的证书完成认证. 更多信息见 [RFC7540] 第 9.1.1 节. 这包括验证 host 与证书 "subjectAltName" 字段中的 "dNSName" 值匹配, 使用 [RFC2818] 中定义的规则. 另见 [RFC5280] 第 4.2.1.6 节.

此外, 客户端MAY避免查询 DNS 来为 Origin Set 中 origins 的新请求建立连接权威性. 但是, 这样做的客户端会面临第 4 节解释的新风险.

由于 ORIGIN 可以随时间改变连接用于的一组 origins, 客户端可能在任何时候都对同一 origin 打开多个可用连接. 发生这种情况时, 如果某连接的 Origin Set 是另一个连接 Origin Set 的真子集, 客户端SHOULD NOT在该连接上发出新请求, 并且在所有未完成请求得到满足后SHOULD关闭该连接.

Origin Set 不受服务器发布的任何 alternative services [RFC7838] 通告影响. 通告 alternative service 不影响服务器是否具有权威性.