Internet Engineering Task Force (IETF) M. Belshe
Request for Comments: 7540 BitGo
Category: Standards Track R. Peon
ISSN: 2070-1721 Google, Inc
M. Thomson, Ed.
Mozilla
2015年5月

超文本传输​​协议版本2(HTTP/2)

摘要

本规范描述超文本传输​​协议(HTTP)语义的一种优化表达,称为 HTTP 版本 2(HTTP/2)。 HTTP/2 通过引入报头字段压缩并允许在同一连接上进行多个并发交换,可以更有效地利用网络资源并减少感知的延迟。 它还引入从服务器到客户端的主动推送。

该规范是 HTTP/1.1 消息语法的一个替代,但并不废弃 HTTP/1.1。 HTTP 的现有语义保持不变。

该备忘录的状态

这是一个Internet标准跟踪文档。

本文档是Internet工程任务组(IETF)的产品。 它代表了IETF社区的共识。 它已经接受了公众审查,并已被Internet工程指导小组(IESG)批准发布。 有关Internet标准的更多信息,请参见RFC 5741的第2部分

可以在http://www.rfc-editor.org/info/rfc7540上获取有关本文档当前状态,任何勘误以及如何提供反馈的信息。

版权声明

Copyright (c) 2015 IETF Trust 和确定为本文档作者的人员。 版权所有。

本文档受BCP 78和IETF信托有关IETF文档(http://trustee.ietf.org/license-info)的法律规定的约束。本文档的出版日期。 请仔细阅读这些文档,因为它们描述了您对本文档的权利和限制。 从本文档中提取的代码组件必须包含《信托法律条款》第4.e节中所述的BSD简化许可证文本,并且如BSD简化许可证中所述,不附带任何保证。

目录

   1. Introduction ....................................................4
   2. HTTP/2 Protocol Overview ........................................5
      2.1. Document Organization ......................................6
      2.2. Conventions and Terminology ................................6
   3. Starting HTTP/2 .................................................7
      3.1. HTTP/2 Version Identification ..............................8
      3.2. Starting HTTP/2 for "http" URIs ............................8
           3.2.1. HTTP2-Settings Header Field .........................9
      3.3. Starting HTTP/2 for "https" URIs ..........................10
      3.4. Starting HTTP/2 with Prior Knowledge ......................10
      3.5. HTTP/2 Connection Preface .................................11
   4. HTTP Frames ....................................................12
      4.1. Frame Format ..............................................12
      4.2. Frame Size ................................................13
      4.3. Header Compression and Decompression ......................14
   5. Streams and Multiplexing .......................................15
      5.1. Stream States .............................................16
           5.1.1. Stream Identifiers .................................21
           5.1.2. Stream Concurrency .................................22
      5.2. Flow Control ..............................................22
           5.2.1. Flow-Control Principles ............................23
           5.2.2. Appropriate Use of Flow Control ....................24
      5.3. Stream Priority ...........................................24
           5.3.1. Stream Dependencies ................................25
           5.3.2. Dependency Weighting ...............................26
           5.3.3. Reprioritization ...................................26
           5.3.4. Prioritization State Management ....................27
           5.3.5. Default Priorities .................................28
      5.4. Error Handling ............................................28
           5.4.1. Connection Error Handling ..........................29
           5.4.2. Stream Error Handling ..............................29
           5.4.3. Connection Termination .............................30
      5.5. Extending HTTP/2 ..........................................30
   6. Frame Definitions ..............................................31
      6.1. DATA ......................................................31
      6.2. HEADERS ...................................................32
      6.3. PRIORITY ..................................................34
      6.4. RST_STREAM ................................................36
      6.5. SETTINGS ..................................................36
           6.5.1. SETTINGS Format ....................................38
           6.5.2. Defined SETTINGS Parameters ........................38
           6.5.3. Settings Synchronization ...........................39
      6.6. PUSH_PROMISE ..............................................40
      6.7. PING ......................................................42
      6.8. GOAWAY ....................................................43
      6.9. WINDOW_UPDATE .............................................46
           6.9.1. The Flow-Control Window ............................47
           6.9.2. Initial Flow-Control Window Size ...................48
           6.9.3. Reducing the Stream Window Size ....................49
      6.10. CONTINUATION .............................................49
   7. Error Codes ....................................................50
   8. HTTP Message Exchanges .........................................51
      8.1. HTTP Request/Response Exchange ............................52
           8.1.1. Upgrading from HTTP/2 ..............................53
           8.1.2. HTTP Header Fields .................................53
           8.1.3. Examples ...........................................57
           8.1.4. Request Reliability Mechanisms in HTTP/2 ...........60
      8.2. Server Push ...............................................60
           8.2.1. Push Requests ......................................61
           8.2.2. Push Responses .....................................63
      8.3. The CONNECT Method ........................................64
   9. Additional HTTP Requirements/Considerations ....................65
      9.1. Connection Management .....................................65
           9.1.1. Connection Reuse ...................................66
           9.1.2. The 421 (Misdirected Request) Status Code ..........66
      9.2. Use of TLS Features .......................................67
           9.2.1. TLS 1.2 Features ...................................67
           9.2.2. TLS 1.2 Cipher Suites ..............................68
   10. Security Considerations .......................................69
      10.1. Server Authority .........................................69
      10.2. Cross-Protocol Attacks ...................................69
      10.3. Intermediary Encapsulation Attacks .......................70
      10.4. Cacheability of Pushed Responses .........................70
      10.5. Denial-of-Service Considerations .........................70
           10.5.1. Limits on Header Block Size .......................71
           10.5.2. CONNECT Issues ....................................72
      10.6. Use of Compression .......................................72
      10.7. Use of Padding ...........................................73
      10.8. Privacy Considerations ...................................73
   11. IANA Considerations ...........................................74
      11.1. Registration of HTTP/2 Identification Strings ............74
      11.2. Frame Type Registry ......................................75
      11.3. Settings Registry ........................................75
      11.4. Error Code Registry ......................................76
      11.5. HTTP2-Settings Header Field Registration .................77
      11.6. PRI Method Registration ..................................78
      11.7. The 421 (Misdirected Request) HTTP Status Code ...........78
      11.8. The h2c Upgrade Token ....................................78
   12. References ....................................................79
      12.1. Normative References .....................................79
      12.2. Informative References ...................................81
   Appendix A. TLS 1.2 Cipher Suite Black List .......................83
   Acknowledgements ..................................................95
   Authors' Addresses ................................................96

1. 介绍

超文本传输​​协议(HTTP)是非常成功的协议。 但是,HTTP/1.1 使用底层传输方式([RFC7230],第 6 节)的特点对当今的应用程序性能产生了负面影响。

特别是,HTTP/1.0 在给定的 TCP 连接上一次仅允许一个未完成的请求。 HTTP/1.1 添加了请求流水线处理,但这仅部分解决了请求并发问题并且仍然受到行头阻塞的困扰。 因此,需要发出许多请求的 HTTP/1.0 和 HTTP/1.1 客户端使用与服务器的多个连接以实现并发性从而减少延迟。

此外,HTTP 报头字段通常是重复且冗长的,从而导致不必要的网络流量,并导致初始 TCP [TCP]拥塞窗口迅速填充。 当在一个新的 TCP 连接上发出多个请求时,这可能导致过多的延迟。

HTTP/2 通过定义 HTTP 语义到底层连接的一个优化映射来解决这些问题。 具体来说,它允许在同一连接上交织请求和响应消息,并对HTTP标头字段使用有效的编码。 它还允许对请求进行优先级排序,使更重要的请求更快地完成,从而进一步提高性能。

生成的协议对网络更友好,因为与 HTTP/1.x 相比,可以使用更少的 TCP 连接。 这意味着与其他流量的竞争减少,连接寿命更长,进而可以更好地利用可用网络容量。

最后,HTTP/2 还可以通过使用二进制消息帧来更有效地处理消息。

2. HTTP/2 协议概述

HTTP/2 为 HTTP 语义提供了优化的传输。 虽然 HTTP/2 支持 HTTP/1.1 的所有核心功能,但其目标是通过多种方式变得更加高效。

HTTP/2 中的基本协议单元是帧(第4.1节)。 每种帧类型都有不同的用途。 例如,HEADERS 和 DATA 帧构成 HTTP 请求和响应的基础(第8.1节);其它类型帧(如 SETTINGS、WINDOW_UPDATE 和 PUSH_PROMISE)用于支持 HTTP/2 的其它功能。

通过使每个 HTTP 请求/响应交换与其自己的流相关联来实现请求的复用(第5节)。 流在很大程度上彼此独立,因此阻塞或停止的请求或响应不会阻止其他流的进度。

流控制和优先级确保可以有效地使用多路复用流。 流控制(第5.2节)有助于确保仅传输可以由接收器使用的数据。 优先级划分(第5.3节)确保可以将有限的资源首先定向到最重要的流。

HTTP/2 添加一种新的交互模式是服务器可以将响应推送到客户端(第8.2节)。 服务器推送允许服务器预测客户端需要的数据并发送到客户端,从而权衡网络使用情况和潜在的延迟增加。 服务器通过合成请求来完成此任务,并以PUSH_PROMISE帧的形式发送。 然后,服务器可以在单独的流上发送对合成请求的响应。

由于连接中使用的 HTTP 报头字段可能包含大量冗余数据,因此包含它们的帧将被压缩(4.3节)。 这对常见大小的请求具有特别有利的影响,因为这允许将许多请求压缩到一个数据包中。

2.1. 文档结构

HTTP/2 规范分为四个部分:

o 启动 HTTP/2(第3节)介绍如何发起 HTTP/2 连接。

o 帧(第4)和流(第5)层描述 HTTP/2 帧的结构和形成多路复用流的方式。

o 帧(第6节)和错误(第7节)定义包括 HTTP/2 中使用的帧和错误类型的详细信息。

o HTTP 映射(第8节)和其他要求(第9节)描述如何使用帧和流来表示 HTTP 语义。

尽管某些帧和流层概念与HTTP隔离,但是此规范并未定义完全通用的帧层。 帧和流层是根据HTTP协议和服务器推送的需求量身定制的。

2.2. 约定和术语

本文档中的关键字“必须”,“不得”,“必须”,“应”,“应禁止”,“应”,“不应”,“建议”,“可以”和“可选”是按照RFC 2119 [RFC2119]中所述进行解释。

所有数值均以网络字节顺序排列。 除非另有说明,否则值是无符号的。 适当时以十进制或十六进制提供字面值。 十六进制字面值以“0x”为前缀,以区别于十进制字面值。

使用以下术语:

客户端:

启动 HTTP/2 连接的端点。 客户端发送 HTTP 请求并接收 HTTP 响应。

连接:

两个端点之间的传输层连接。

连接错误:

影响整个 HTTP/2 连接的错误。

端点:

连接的客户端或服务器。

帧:

HTTP / 2连接中的最小通信单元,由头和根据帧类型构造的八位字节的可变长度序列组成。

对端:

一个端点。 在讨论一个特定端点时,“对端”是指远程的另一端点。

接收者:

正在接收帧的端点。

发送者:

正在传输帧的端点。

服务器:

接受 HTTP/2 连接的端点。 服务器接收 HTTP 请求并发送 HTTP 响应。

流:

HTTP/2 连接内的双向帧流。

流错误:

一个 HTTP/2 流上的错误。

最后,术语“网关”、“中介”、“代理”和“隧道”在[RFC7230] 的第 2.3 节中定义。 中介在不同时间充当客户端和服务器。

[RFC7230] 的第 3.3 节中定义了“有效载荷主体”一词。

3. 启动 HTTP/2

HTTP/2 连接是在 TCP 连接([TCP])之上运行的应用程序层协议。 客户端是 TCP 连接的发起者。

HTTP/2 使用与 HTTP/1.1 相同的“http”和“https”URI 方案。 HTTP/2 共享相同的默认端口号:“http” URI 为 80,“https”URI 为 443。 所以,处理“http://example.org/foo”或“https://example.com/bar”这样的目标资源 URI 请求需要首先发现上游服务器(客户端希望建立连接的对端)是否支持 HTTP/2。

确定支持 HTTP/2 的方式对于“http”和“https” URI 是不同的。 第 3.2 节介绍“http” URI 的发现。 第 3.3 节介绍“https” URI 的发现。

3.1. HTTP/2 版本识别

本文档中定义的协议具有两个标识符。

o 字符串“h2”标识 HTTP/2 使用传输层安全(TLS)[TLS12]协议。 这个标识符用于 TLS 应用程序层协议协商(ALPN)扩展 [TLS-ALPN] 字段以及任何标识 TLS 上的 HTTP/2 的地方。

“h2”字符串序列化为两个八位字节序列的 ALPN 协议标识符:0x68、0x32。

o 字符串“h2c”标识 HTTP/2 在明文 TCP 上运行的协议。 这个标识符用于 HTTP/1.1 Upgrade 头部字段以及标识 TCP 上的 HTTP/2 的任何地方。

“h2c”是 ALPN 标识符空间保留的字符串,但是描述的是不使用 TLS 的协议。

协商“h2”或“h2c”暗含使用本文档中描述的传输、安全、帧和消息语义。

3.2. 为“http” URI 启动 HTTP/2

在不具有下一跳是否支持 HTTP/2 的先验知识的情况下,请求“http”URI 的客户端使用 HTTP 升级机制([RFC7230]的6.7节)。 客户端通过发出 HTTP/1.1 请求并包括带有“h2c”令牌的 Upgrade 报头字段来做到这一点。 这样的 HTTP/1.1 请求必须仅包含一个 HTTP2-Settings(3.2.1节)报头字段。

例如:

GET / HTTP/1.1
Host: server.example.com
Connection: Upgrade, HTTP2-Settings
Upgrade: h2c
HTTP2-Settings: <base64url encoding of HTTP/2 SETTINGS payload>

在客户端可以发送 HTTP/2 帧之前,必须完整发送包含有效内容主体的请求。 这意味着较大的请求可能会阻止连接的使用,直到完全发送为止。

如果初始请求与后续请求的并发性很重要,则可以使用 OPTIONS 请求执行到 HTTP/2 的升级,但要付出额外的往返代价。

不支持 HTTP/2 的服务器可以响应该请求,就像 Upgrade 报头字段不存在一样:

HTTP/1.1 200 OK
Content-Length: 243
Content-Type: text/html

...

服务器必须忽略 Upgrade 报头字段中的“h2”标记。 带有“h2”的标记表示通过 TLS 的 HTTP/2,而TLS 上的 HTTP/2 是按照 3.3 节中所述进行协商的。

支持 HTTP/2 的服务器以响应码 101(交换协议)接受升级。 在 101 响应之后有一个空行,然后服务器可以开始发送 HTTP/2 帧。 这些帧必须包括对发起升级请求的响应。

例如:

HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: h2c

[ HTTP/2 connection ...

服务器发送的第一个 HTTP/2 帧必须是服务器的连接前言(第3.5节),它由一个 SETTINGS 帧(第6.5节)组成。 收到 101 响应后,客户端必须发送连接前言(第3.5),该前言包括一个 SETTINGS 帧。

在升级之前发送的 HTTP/1.1 请求分配的流标识符为 1(请参见第 5.1.1 节),具有默认优先级(第5.3.5 节)。 从客户端到服务器流 1 隐含是“半关闭”的(请参见第 5.1 节),因为该请求已作为 HTTP/1.1 请求完成。 开始 HTTP/2 连接后,流 1 用于响应。

3.2.1. HTTP2-Settings 报头字段

从 HTTP/1.1 升级到 HTTP/2 的请求务必包含一个“HTTP2-Settings”报头字段。 HTTP2-Settings 是与特定连接相关的报头字段,其中包含控制 HTTP/2 连接的参数,用于期望服务器接受升级请求。

HTTP2-Settings = token68

如果此报头字段不存在或存在多个,则服务器不得将连接升级到 HTTP/2。 服务器不得发送此报头字段。

HTTP2-Settings 报头字段的内容是 SETTINGS 帧(第 6.5 节)的有效载荷,编码为 base64url 字符串(即 [RFC4648] 的第 5 节描述的,URL 和文件名安全的 Base64 编码并省略结尾的所有'='字符)。 [token68] 的 ABNF [RFC5234] 生成在 [RFC7235] 的 2.1 节中定义。

由于升级仅适用于直接连接,因此发送HTTP2-Settings头字段的客户端还必须在Connection头字段中发送“ HTTP2-Settings”作为连接选项,以防止转发(请参见[RFC7230]的6.1节)。

服务器像对其他任何SETTINGS帧一样对这些值进行解码和解释。 无需显式确认这些设置(第6.5.3节),因为101响应用作隐式确认。 在升级请求中提供这些值使客户端有机会在从服务器接收任何帧之前提供参数。

3.3. 为“https” URI 启动 HTTP/2

发出“https” URI 请求的客户端使用应用层协议协商(ALPN)扩展 [TLS-ALPN] 的 TLS [TLS12]。

TLS 上的 HTTP/2 使用“h2”协议标识符。 “h2c”协议标识符不得由客户端发送或由服务器选择;“h2c”协议标识符描述不使用 TLS 的协议。

TLS协商完成后,客户端和服务器都必须发送连接前言(第3.5节)。

3.4. 以先验知识开始 HTTP/2

客户端可以通过其他方式得知特定服务器支持 HTTP/2。 例如,[ALT-SVC] 描述了一种广告此功能的机制。

客户端必须发送连接前言(第3.5节),然后可以立即将 HTTP/2 帧发送到这样的服务器;服务器可以通过存在连接前言来识别这些连接。 这仅影响通过明文 TCP 的 HTTP/2 连接的建立。在 TLS上 支持 HTTP/2 的实现必须使用 TLS [TLS-ALPN] 中的协议协商。

同样,服务器必须发送连接前言(第3.5节)。

如果没有额外的信息,一个给定的服务器之前支持 HTTP/2 并不足以表明对未来的连接同样支持 HTTP/2。 例如,服务器配置可能会更改、集群服务器中实例之间的配置可能会更改,或者网络条件可能会更改。

3.5. HTTP/2 连接前言

在 HTTP/2 中,要求每个端点发送连接序言作为对所使用协议的最终确认,并为 HTTP/2 连接建立初始设置。 客户端和服务器各自发送不同的连接序言。

客户端连接前言以24个八位位组的序列开头,十六进制表示为:

0x505249202a20485454502f322e300d0a0d0a534d0d0a0d0a

也就是说,连接序言以字符串"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"开头。 此序列之后必须紧跟一个 SETTINGS 帧(第6.5节),该帧可以为空。 客户端在收到101(交换协议)响应(表示升级成功)或作为TLS连接的第一个应用程序数据八位字节后立即发送客户端连接序言。 如果使用服务器对协议的先验知识开始 HTTP/2 连接,则在建立连接时发送客户端连接序言。

注意:选择客户端连接前言是为了使大部分 HTTP/1.1 或 HTTP/1.0 服务器和中介都不会尝试处理其他帧。 请注意,这不能解决[TALKING]中提出的问题。

服务器连接序言由可能为空的 SETTINGS 帧(第 6.5 节)组成,该帧必须是服务器在 HTTP/2 连接中发送的第一帧。

发送连接序言后,必须确认从对等方收到的作为连接序言一部分的SETTINGS帧(请参阅6.5.3节)。

为了避免不必要的延迟,允许客户端在发送客户端连接序言之后立即向服务器发送其他帧,而不必等待接收服务器连接序言。 但是,请务必注意,服务器连接前言SETTINGS框架可能包含一些参数,这些参数必定会更改期望客户端与服务器通信的方式。 在接收到SETTINGS帧后,客户端应遵守所有已建立的参数。 在某些配置中,服务器有可能在客户端发送其他帧之前传输设置,从而提供了避免此问题的机会。

客户端和服务器必须将无效的连接前言视为类型为PROTOCOL_ERROR的连接错误(第5.4.1节)。 在这种情况下,可以忽略 GOAWAY 帧(第 6.8 节),因为无效的前言表示对端未使用 HTTP/2。

4. HTTP 帧

建立 HTTP/2 连接后,端点之间即可开始交换帧。

4.1. 帧格式

所有帧均以固定的 9 个字节首部开头,后跟可变长度的有效负载。

    +-----------------------------------------------+
    |                 Length (24)                   |
    +---------------+---------------+---------------+
    |   Type (8)    |   Flags (8)   |
    +-+-------------+---------------+-------------------------------+
    |R|                 Stream Identifier (31)                      |
    +=+=============================================================+
    |                   Frame Payload (0...)                      ...
    +---------------------------------------------------------------+
    
                          图 1:帧的结构
    

帧头的字段定义为:

长度:

帧有效载荷的长度,表示为无符号的24位整数。 除非接收者为SETTINGS_MAX_FRAME_SIZE设置了更大的值,否则不得发送大于 2^14(16,384)的值。

帧头部的 9 个字节不包含在该值中。

类型:

帧的类型,用 8 个二进制位表示。 帧的类型决定帧的格式和语义。 具体的实现必须忽略并丢弃未知的任何类型的帧。

标志:

为特定于帧类型的布尔标志保留的8位字段。

为标志分配特定于所指示帧类型的语义。 对于特定帧类型,没有定义语义的标志必须被忽略,并且在发送时必须置为未设置(0x0)。

R:

保留的1位字段。 该位的语义是不确定的,发送时该位必须保持未设置(0x0),接收时该位必须被忽略。

流标识符:

流标识符(请参阅第5.1.1节),以无符号的31位整数表示。 值0x0保留给与整个连接相关联的帧,而不是单个流。

帧有效负载的结构和内容完全取决于帧类型。

4.2. 帧大小

帧有效负载的大小受接收方在 SETTINGS_MAX_FRAME_SIZE 设置中发布的最大大小限制。 此设置的值可以介于 2^14(16,384)和 2^24-1(16,777,215)个八位位组(含)之间。

所有实现都必须能够接收和最小处理长度最大为 2^14 个八位位组的帧,以及 9 个八位位组的帧头(4.1节)。 描述帧大小时不包括帧头的大小。

注意:某些帧类型,例如PING(第6.7节),对允许的有效负载数据量施加了额外的限制。

如果帧超过SETTINGS_MAX_FRAME_SIZE中定义的大小,超过帧类型定义的任何限制或者太小而不能包含必需的帧数据,则端点必须发送FRAME_SIZE_ERROR的错误代码。 可能会改变整个连接状态的帧中的帧大小错误必须视为连接错误(5.4.1节);这包括任何带有标题块(第4.3)(即HEADERS,PUSH_PROMISE和CONTINUATION),SETTINGS的帧,以及任何流标识符为0的帧。

端点没有义务使用帧中的所有可用空间。 通过使用小于允许的最大大小的帧,可以提高响应能力。 发送大帧可能会导致延迟时间敏感帧(例如RST_STREAM,WINDOW_UPDATE或PRIORITY)的发送,如果被大帧传输所阻止,则可能会影响性能。

4.3. 报头的压缩和解压

就像 HTTP/1 中一样,HTTP/2中 的报头字段是具有一个或多个关联值的名称。 标头字段用于HTTP请求和响应消息以及服务器推送操作中(请参见第8.2部分)。

标头列表是零个或多个标头字段的集合。 通过连接传输时,头文件列表会使用HTTP头压缩[COMPRESSION]序列化为头文件。 然后,已序列化的标题块被分为一个或多个八位字节序列,称为标题块片段,并在HEADERS(第6.2),PUSH_PROMISE(第6.6)的有效载荷内传输或CONTINUATION(第6.10节)帧。

HTTP映射对Cookie头字段[COOKIE]进行了特殊处理(请参见第8.1.2.5节)。

接收端点通过串联其片段来重组头块,然后解压缩该块以重建头列表。

完整的标题块包括以下任一项:

o 设置了END_HEADERS标志的单个HEADERS或PUSH_PROMISE帧,或者

o 清除了END_HEADERS标志的HEADERS或PUSH_PROMISE帧和一个或多个CONTINUATION帧,其中最后一个CONTINUATION帧设置了END_HEADERS标志。

标头压缩是有状态的。 一个压缩上下文和一个解压缩上下文用于整个连接。 报头块中的解码错误必须视为COMPRESSION_ERROR类型的连接错误(5.4.1节)。

每个标题块都作为离散单元进行处理。 报头块必须作为连续的帧序列发送,没有任何其他类型或来自任何其他流的交织帧。 HEADERS或CONTINUATION帧序列中的最后一个帧设置了END_HEADERS标志。 PUSH_PROMISE或CONTINUATION帧序列中的最后一个帧设置了END_HEADERS标志。 这允许报头块在逻辑上等效于单个帧。

报头块片段只能作为HEADERS,PUSH_PROMISE或CONTINUATION帧的有效载荷发送,因为这些帧携带可以修改接收方维护的压缩上下文的数据。 即使要丢弃帧,接收HEADERS,PUSH_PROMISE或CONTINUATION帧的端点也需要重新组装头块并执行解压缩。 如果接收方未解压缩首部块,则必须以类型为COMPRESSION_ERROR的连接错误(第5.4.1节)终止连接。

5. 流和多路复用

“流”是HTTP / 2连接中客户端和服务器之间交换的独立的双向帧序列。 流具有几个重要特征:

o 单个HTTP / 2连接可以包含多个并发打开的流,其中任一端点都可以交错多个流中的帧。

o 流可以单方面建立和使用,也可以由客户端或服务器共享。

o 可以通过任一端点关闭流。

o 在流上发送帧的顺序很重要。 收件人按接收顺序处理帧。 特别地,HEADERS和DATA帧的顺序在语义上很重要。

o 流由整数标识。 通过端点启动流,将流标识符分配给流。

5.1. 流状态

流的生命周期如图2所示。


                                +--------+
                        send PP |        | recv PP
                       ,--------|  idle  |--------.
                      /         |        |         \
                     v          +--------+          v
              +----------+          |           +----------+
              |          |          | send H /  |          |
       ,------| reserved |          | recv H    | reserved |------.
       |      | (local)  |          |           | (remote) |      |
       |      +----------+          v           +----------+      |
       |          |             +--------+             |          |
       |          |     recv ES |        | send ES     |          |
       |   send H |     ,-------|  open  |-------.     | recv H   |
       |          |    /        |        |        \    |          |
       |          v   v         +--------+         v   v          |
       |      +----------+          |           +----------+      |
       |      |   half   |          |           |   half   |      |
       |      |  closed  |          | send R /  |  closed  |      |
       |      | (remote) |          | recv R    | (local)  |      |
       |      +----------+          |           +----------+      |
       |           |                |                 |           |
       |           | send ES /      |       recv ES / |           |
       |           | send R /       v        send R / |           |
       |           | recv R     +--------+   recv R   |           |
       | send R /  `----------->|        |<-----------'  send R / |
       | recv R                 | closed |               recv R   |
       `----------------------->|        |<----------------------'
                                +--------+
    
          send:   endpoint sends this frame
          recv:   endpoint receives this frame
    
          H:  HEADERS frame (with implied CONTINUATIONs)
          PP: PUSH_PROMISE frame (with implied CONTINUATIONs)
          ES: END_STREAM flag
          R:  RST_STREAM frame
    
                          图 2:流的状态
    

请注意,此图显示了流状态转换以及仅影响这些转换的帧和标志。 在这方面,CONTINUATION帧不会导致状态转换。它们实际上是它们遵循的HEADERS或PUSH_PROMISE的一部分。

为了进行状态转换,将END_STREAM标志作为对其承载帧的单独事件进行处理。设置了END_STREAM标志的HEADERS帧可能导致两个状态转换。

两个端点都具有流状态的主观视图,当传输帧时,状态可能会有所不同。 端点不协调流的创建;它们是由任一端点单方面创建的。 状态不匹配的负面影响仅限于发送RST_STREAM之后的“关闭”状态,其中在关闭后的一段时间内可能会接收到帧。

流具有以下状态:

空闲:

所有流都以“空闲”状态开始。

从此状态开始,以下转换有效:

* 发送或接收HEADERS帧会使流变为“打开”。 第5.1.1节所述选择流标识符。 相同的HEADERS帧还可以使流立即变为“半封闭”。

* 在另一个流上发送PUSH_PROMISE帧将保留标识为以后使用的空闲流。 保留流的流状态转换为“保留(本地)”。

* 在另一个流上接收PUSH_PROMISE帧将保留一个空闲流,该空闲流将被标识以供以后使用。 保留流的流状态转换为“保留(远程)”。

* 请注意,PUSH_PROMISE帧不是在空闲流上发送的,而是在Promised Stream ID字段中引用新保留的流。

在这种状态下,在流上接收到除HEADERS或PRIORITY以外的任何帧,必须将其视为PROTOCOL_ERROR类型的连接错误(5.4.1节)。

保留(本地):

处于“保留(本地)”状态的流是通过发送PUSH_PROMISE帧承诺的。 PUSH_PROMISE帧通过将流与远程对等方启动的开放流相关联来保留空闲流(请参见第8.2节)。

在这种状态下,只能进行以下转换:

* 端点可以发送HEADERS帧。 这将导致流以“半关闭(远程)”状态打开。

* 任一端点均可发送RST_STREAM帧以使流“关闭”。 这将释放流保留。

在这种状态下,端点不得发送除HEADERS,RST_STREAM或PRIORITY以外的任何类型的帧。

在这种状态下可以接收一个PRIORITY或WINDOW_UPDATE帧。 在这种状态下,在流上接收除RST_STREAM,PRIORITY或WINDOW_UPDATE以外的任何类型的帧,都必须视为PROTOCOL_ERROR类型的连接错误(5.4.1节)。

保留(远程):

处于“已保留(远程)”状态的流已由远程对等方保留。

在这种状态下,只能进行以下转换:

* 接收HEADERS帧会使流转换为“半封闭(本地)”。

* 任一端点均可发送RST_STREAM帧以使流“关闭”。 这将释放流保留。

端点可以在这种状态下发送一个PRIORITY帧来重新排序保留的流。 在这种状态下,端点不得发送除RST_STREAM,WINDOW_UPDATE或PRIORITY以外的任何类型的帧。

在此状态下,在流上接收除HEADERS,RST_STREAM或PRIORITY以外的任何类型的帧,都必须视为PROTOCOL_ERROR类型的连接错误(5.4.1节)。

打开:

两个对等方都可以使用处于“开放”状态的流来发送任何类型的帧。 在这种状态下,发送对等方遵守通告的流级别流控制限制(第5.2节)。

从此状态,任一端点都可以发送设置了END_STREAM标志的帧,这将导致流转换为“半关闭”状态之一。 发送END_STREAM标志的端点使流状态变为“半封闭(本地)”;接收到END_STREAM标志的端点使流状态变为“半关闭(远程)”。

任一端点均可从此状态发送RST_STREAM帧,从而使其立即转换为“已关闭”。

半关闭(本地):

处于“半封闭(本地)”状态的流不能用于发送WINDOW_UPDATE,PRIORITY和RST_STREAM以外的帧。

当收到包含END_STREAM标志的帧或任一对等方发送RST_STREAM帧时,流将从此状态转换为“关闭”。

端点可以在此状态下接收任何类型的帧。 要继续接收流控制的帧,必须使用WINDOW_UPDATE帧提供流控制信用。 在这种状态下,接收器可以忽略WINDOW_UPDATE帧,这些帧可能在发送带有END_STREAM标志的帧后的短时间内到达。

在此状态下接收的优先级帧用于重新确定依赖于已标识流的流的优先级。

半关闭(远程):

对等方不再使用“半关闭(远程)”流发送帧。 在此状态下,端点不再必须维护接收器流控制窗口。

如果端点收到处于此状态的流的WINDOW_UPDATE,PRIORITY或RST_STREAM以外的其他帧,则该端点必须以STREAM_CLOSED类型的流错误(5.4.2)进行响应。

端点可以使用“半封闭(远程)”流发送任何类型的帧。 在这种状态下,端点继续遵守通告的流级别流控制限制(第5.2节)。

通过发送包含END_STREAM标志的帧或任何一个对等方发送RST_STREAM帧,流都可以从此状态转换为“关闭”。

关闭:

“关闭”状态是终端状态。

端点不得在封闭流上发送除优先级以外的帧。 接收到RST_STREAM后接收到除PRIORITY以外的任何帧的端点必须将其视为STREAM_CLOSED类型的流错误(5.4.2节)。 类似地,在接收到设置了END_STREAM标志的帧之后接收任何帧的端点必须将其视为STREAM_CLOSED类型的连接错误(5.4.1节),除非如下所述允许该帧。

发送包含END_STREAM标志的DATA或HEADERS帧后,可以在此状态下短时间内接收WINDOW_UPDATE或RST_STREAM帧。 在远程对等方接收并处理RST_STREAM或带有END_STREAM标志的帧之前,它可能会发送这些类型的帧。 端点必须忽略在这种状态下接收到的WINDOW_UPDATE或RST_STREAM帧,尽管端点可以选择将发送END_STREAM之后很长时间到达的帧视为PROTOCOL_ERROR类型的连接错误(5.4.1节)。

可以在封闭流上发送优先级帧,以区分依赖于封闭流的流的优先级。 端点应该处理优先级帧,但是如果从依赖关系树中删除了流,则可以忽略它们(请参阅第5.3.4节)。

如果由于发送RST_STREAM帧而达到此状态,则接收RST_STREAM的对等方可能已经发送了(或已排队发送)无法撤消的流上的帧。 端点发送RST_STREAM帧后,必须忽略其在关闭流上接收的帧。 端点可以选择限制其忽略帧的时间段,并将在此时间之后到达的帧视为错误。

发送RST_STREAM之后收到的流控制帧(即DATA)计入连接流控制窗口。 即使这些帧可能会被忽略,因为它们是在发送方接收RST_STREAM之前发送的,因此发送方将考虑将这些帧计入流控制窗口。

端点在发送RST_STREAM之后可能会收到PUSH_PROMISE帧。 即使相关联的流已被重置,PUSH_PROMISE也会使流变为“保留”。 因此,需要RST_STREAM来关闭不需要的承诺流。

在本文档中其他地方没有更具体的指导的情况下,实现应将状态描述中未明确允许的帧接收视为连接错误(第5.4.1节)类型协议错误。 注意,可以在任何流状态下发送和接收优先级。 未知类型的帧将被忽略。

第8.1节中可以找到HTTP请求/响应交换的状态转换示例。 服务器推送状态转换的示例可以在8.2.18.2.2中找到。

5.1.1. 流标识符

流用无符号的31位整数标识。 客户端发起的流必须使用奇数流标识符;由服务器启动的那些务必使用偶数流标识符。 流标识符零(0x0)用于连接控制消息;流标识符零不能用于建立新流。

升级到HTTP / 2的HTTP / 1.1请求(请参见第3.2节)以流标识符1(0x1)进行响应。 升级完成后,流0x1被“半关闭(本地)”到客户端。 因此,从HTTP / 1.1升级的客户端无法将流0x1选择为新的流标识符。

新建立的流的标识符必须在数值上大于发起端点已打开或保留的所有流。 这控制使用HEADERS帧打开的流和使用PUSH_PROMISE保留的流。 收到意外流标识符的端点必须以类型PROTOCOL_ERROR的连接错误(5.4.1)进行响应。

第一次使用新的流标识符会隐式关闭处于“空闲”状态的所有流,该流可能已由该对等方使用值较低的流标识符启动。 例如,如果客户端在流7上发送HEADERS帧而没有在流5上发送帧,则当发送或接收流7的第一个帧时,流5转换为“关闭”状态。

流标识符不能重复使用。 长期连接会导致端点耗尽可用范围的流标识符。 无法建立新的流标识符的客户端可以为新的流建立新的连接。 无法建立新流标识符的服务器可以发送GOAWAY帧,以便客户端被迫为新流打开新连接。

5.1.2. 流并发

对等方可以使用SETTINGS帧内的SETTINGS_MAX_CONCURRENT_STREAMS参数(请参阅6.5.2部分)来限制并发活动流的数量。 最大并发流设置特定于每个端点,并且仅适用于接收该设置的对等方。 即,客户端指定服务器可以启动的并发流的最大数量,服务器指定客户端可以启动的并发流的最大数量。

处于“打开”状态或处于“半关闭”状态中的任一流都计入允许端点打开的最大流数。 这三种状态中的任何一种流都将计入SETTINGS_MAX_CONCURRENT_STREAMS设置中公布的限制。 处于任何“保留”状态的流均不会计入流限制。

端点不得超过其对等方设置的限制。 接收到导致其通告的并发流限制被超过的HEADERS帧的端点必须将此视为PROTOCOL_ERROR或REFUSED_STREAM类型的流错误(5.4.2节)。 错误代码的选择确定端点是否希望启用自动重试(有关详细信息,请参见第8.1.4节)。

希望将SETTINGS_MAX_CONCURRENT_STREAMS的值减小到小于当前打开流数的值的端点可以关闭超过新值的流或允许流完成。

5.2. 流量控制

使用流进行多路复用会引起TCP连接使用方面的争用,从而导致流阻塞。 流控制方案可确保同一连接上的流不会造成相消干扰。 流控制既用于单个流,也用于整个连接。

HTTP / 2通过使用WINDOW_UPDATE帧(第6.9节)来提供流控制。

5.2.1. 流量控制原理

HTTP / 2流流控制旨在允许使用各种流控制算法,而无需更改协议。 HTTP / 2中的流控制具有以下特征:

1. 流控制特定于连接。 两种类型的流控制都在单跳的端点之间,而不是在整个端到端路径上。

2. 流控制基于WINDOW_UPDATE帧。 接收方通告它们准备在流上以及整个连接中接收多少个八位位组。 这是基于信用的方案。

3. 流量控制是方向性的,由接收器提供总体控制。 接收者可以选择设置每个流以及整个连接所需的任何窗口大小。 发送方必须遵守接收方施加的流量控制限制。 客户端,服务器和中介都独立地将其流控制窗口发布为接收方,并在发送时遵守其对等方设置的流控制限制。

4. 对于新流和整个连接,流控制窗口的初始值为65,535个八位位组。

5. 帧类型确定流控制是否适用于帧。 在本文档中指定的帧中,只有DATA帧要进行流控制;否则,仅对DATA帧进行流控制。所有其他帧类型都不会在广告流控制窗口中占用空间。 这确保了重要的控制框架不会被流控制阻塞。

6. 流量控制无法禁用。

7. HTTP / 2仅定义WINDOW_UPDATE帧的格式和语义(第6.9节)。 该文件没有规定接收者如何决定何时发送该帧或它发送的值,也没有规定发送者如何选择发送分组。 实现者可以选择任何适合其需求的算法。

实现还负责管理如何根据优先级发送请求和响应,选择如何避免对请求的行头阻塞以及管理新流的创建。 这些算法的选择可以与任何流控制算法交互。

5.2.2. 适当使用流量控制

定义流控制以保护在资源约束下运行的端点。 例如,代理需要在许多连接之间共享内存,并且可能具有较慢的上游连接和较快的下游连接。 流控制解决了以下情况:接收器无法处理一个流上的数据,但希望继续处理同一连接中的其他流。

不需要此功能的部署可以通告最大大小的流控制窗口(2 ^ 31-1),并且可以在接收到任何数据时通过发送WINDOW_UPDATE帧来维护此窗口。 这有效地禁用了该接收器的流控制。 相反,发送方始终要遵守接收方通告的流控制窗口。

具有受限资源(例如,内存)的部署可以采用流控制来限制对等方可以消耗的内存量。 但是请注意,如果在不了解带宽延迟乘积的情况下启用了流控制,这可能导致对可用网络资源的欠佳使用(请参阅[RFC7323])。

即使完全了解当前的带宽延迟产品,执行流控制也可能很困难。 使用流控制时,接收者务必及时从TCP接收缓冲区中读取。 如果未读取并执行关键帧(例如WINDOW_UPDATE),则可能导致死锁。

5.3. 流优先级

客户端可以通过在打开流的HEADERS帧(第6.2节)中包含优先级信息来为新流分配优先级。 在任何其他时间,PRIORITY帧(第6.3节)可用于更改流的优先级。

优先级排序的目的是允许端点表达在管理并发流时希望其对等方分配资源的方式。 最重要的是,当发送能力有限时,可以使用优先级来选择要发送帧的流。

可以通过将流标记为依赖于其他流的完成来区分流的优先级(第5.3.1节)。 每个依赖项被分配一个相对权重,该数字用于确定分配给依赖于相同流的流的可用资源的相对比例。

明确设置流的优先级将输入优先级过程。 它不保证该流相对于任何其他流的任何特定处理或传输顺序。 端点不能强制对等方使用优先级按特定顺序处理并发流。 因此,表达优先权只是一个建议。

优先级信息可以从消息中省略。 在提供任何显式值之前使用默认值(第5.3.5节)。

5.3.1. 流依赖

每个流可以被赋予对另一个流的显式依赖。 包括依赖性表示优先选择将资源分配给所标识的流,而不是分配给依赖性流。

不依赖于任何其他流的流的流依赖性为0x0。 换句话说,不存在的流0形成树的根。

依赖于另一个流的流是从属流。 流所依赖的流是父流。 对当前不在树中的流(例如处于“空闲”状态的流)的依赖性导致该流被赋予默认优先级(第5.3.5节)。

在分配对另一个流的依赖关系时,该流将作为父流的新依赖关系添加。 共享同一父对象的从属流彼此之间没有顺序。 例如,如果流B和C依赖于流A,并且创建的流D依赖于流A,则这将导致A的依赖顺序,然后是B,C和D的任何顺序。

       A                 A
      / \      ==>      /|\
     B   C             B D C
    
             Figure 3: Example of Default Dependency Creation
    

排他标志允许插入新级别的依赖关系。 独占标志使该流成为其父流的唯一依赖项,从而导致其他依赖项变为与该独占流的依赖关系。 在前面的示例中,如果创建的流D具有对流A的独占依赖关系,则这将导致D成为B和C的依赖关系父级。

                         A
       A                 |
      / \      ==>       D
     B   C              / \
                       B   C
    
            Figure 4: Example of Exclusive Dependency Creation
    

在依赖关系树内部,只有在依赖流所有依赖流(父流链最高为0x0)关闭或无法对其进行处理时,才应为该资源分配资源。

流不能依赖于自身。 端点必须将此视为PROTOCOL_ERROR类型的流错误(第5.4.2节)。

5.3.2. 依赖权重

为所有相关流分配了1到256(含)之间的整数权重。

具有相同父项的流应根据其权重按比例分配资源。 因此,如果流B依赖于权重为4的流A,流C依赖于权重为12的流A,并且流A上无法进行任何处理,则流B理想地接收分配给流C的资源的三分之一。

5.3.3. 重新排序

使用PRIORITY框架更改流优先级。 设置依赖关系会导致流变得依赖于已标识的父流。

如果重新确定父级的优先级,则从属流将与其父级流一起移动。 为重定优先级的流设置具有独占标志的依赖关系会导致新父流的所有依赖关系都变得依赖于重定优先级的流。

如果使流依赖于其自身的依赖关系之一,则首先将先前依赖的流移动为依赖于重新排序优先级的流的先前父对象。 移动的依赖项保持其权重。

例如,考虑原始的依赖树,其中B和C依赖于A,D和E依赖于C,F依赖于D。如果使A依赖于D,则D代替A。 除F外,所有其他依赖关系都保持不变,如果重新优先级排他,F将依赖于A。

       x                x                x                 x
       |               / \               |                 |
       A              D   A              D                 D
      / \            /   / \            / \                |
     B   C     ==>  F   B   C   ==>    F   A       OR      A
        / \                 |             / \             /|\
       D   E                E            B   C           B C F
       |                                     |             |
       F                                     E             E
    
                  (intermediate)   (non-exclusive)    (exclusive)
    
                Figure 5: Example of Dependency Reordering
    

5.3.4. 优先状态管理

从依赖关系树中删除流时,可以将其依赖关系移动为依赖于封闭流的父级。 通过基于封闭流依赖关系的权重按比例分配封闭流的依赖关系权重,可以重新计算新依赖关系的权重。

从依赖关系树中删除的流会导致某些优先级信息丢失。 资源在具有相同父流的流之间共享,这意味着如果该集中的流关闭或被阻塞,则分配给该流的任何备用容量都将分配给该流的直接邻居。 但是,如果从树中删除了公共依存关系,则这些流与下一个最高级别的流共享资源。

例如,假设流A和B共享父级,而流C和D都依赖于流A。 在删除流A之前,如果流A和D无法继续,则流C接收专用于流A的所有资源。 如果将流A从树中删除,则流A的权重将在流C和D之间分配。如果流D仍无法继续进行,则导致流C接收到的资源比例减少。 对于相等的起始权重,C接收可用资源的三分之一而不是一半。

在创建依赖于该流的优先级信息时,可能会关闭该流。 如果在依赖项中标识的流没有关联的优先级信息,则将为依赖项流分配默认优先级(第5.3.5节)。 由于可以为流赋予与预期的优先级不同的优先级,因此这可能会导致次优的优先级排序。

为了避免这些问题,端点应该在流关闭后的一段时间内保留流优先级状态。 状态保留的时间越长,为流分配不正确或默认优先级值的机会就越小。

类似地,处于“空闲”状态的流可以被分配优先级或成为其他流的父级。 这允许在依赖关系树中创建分组节点,从而使优先级表达更加灵活。 空闲流以默认优先级开始(第5.3.5节)。

对于未计入SETTINGS_MAX_CONCURRENT_STREAMS设置的限制的流,保留优先级信息可能会给端点造成很大的状态负担。 因此,可以限制保留的优先状态的数量。

端点为优先级维护的其他状态的数量可能取决于负载。在高负载下,可以丢弃优先级状态以限制资源承诺。 在极端情况下,端点甚至可能会丢弃活动或保留流的优先级状态。 如果应用了限制,则端点应至少保持其SETTINGS_MAX_CONCURRENT_STREAMS设置所允许的流数量。 实现也应该尝试为优先级树中正在使用的流保留状态。

如果它已经保留了足够的状态,则接收改变关闭流优先级的PRIORITY帧的端点应该改变依赖于此状态的流的依赖关系。

5.3.5. 默认优先级

最初,为所有流分配对流0x0的非排他性依赖关系。 推送流(第8.2节)最初取决于其关联的流。 在这两种情况下,流均被分配默认权重16。

5.4. 错误处理

HTTP/2 帧允许两类错误:

o 使整个连接无法使用的错误条件是连接错误。

o 单个流中的错误是流错误。

错误代码列表包含在第7节中。

5.4.1. 连接错误处理

连接错误是指阻止进一步处理帧层或破坏任何连接状态的任何错误。

遇到连接错误的端点应该首先发送一个GOAWAY帧(第6.8),该帧带有从其对等方成功接收的最后一个流的流标识符。 GOAWAY框架包含错误代码,该错误代码指示连接终止的原因。 发送GOAWAY帧以解决错误情况后,端点务必关闭TCP连接。

接收端点可能无法可靠地接收GOAWAY([RFC7230],第6.6节描述了立即关闭连接如何导致数据丢失)。 如果出现连接错误,GOAWAY仅提供最大努力尝试与对等方进行通信,以说明为什么终止连接。

端点可以随时终止连接。 特别是,端点可以选择将流错误视为连接错误。 端点应在结束连接时发送GOAWAY帧,前提是情况允许。

5.4.2. 流错误处理

流错误是与特定流相关的错误,不影响其他流的处理。

检测到流错误的端点发送RST_STREAM帧(第6.4节),其中包含发生错误的流的流标识符。 RST_STREAM帧包括指示错误类型的错误代码。

RST_STREAM是端点可以在流上发送的最后一个帧。 发送RST_STREAM帧的对等体必须准备好接收远程对等体发送或排队发送的任何帧。 这些帧可以被忽略,除非它们修改了连接状态(例如,为报头压缩(4.3节)或流控制而保持的状态)。

通常,端点不应为任何流发送多个RST_STREAM帧。 但是,如果端点在往返时间以上之后在封闭流上接收到帧,则可以发送其他RST_STREAM帧。 允许此行为处理行为异常的实现。

为了避免循环,端点不得发送RST_STREAM作为对RST_STREAM帧的响应。

5.4.3. 连接终止

如果在流保持“打开”或“半关闭”状态时关闭或重置TCP连接,则无法自动重试受影响的流(有关详细信息,请参见第8.1.4节)。

5.5. 扩展 HTTP/2

HTTP / 2允许扩展协议。 在本节描述的限制范围内,协议扩展可用于提供其他服务或更改协议的任何方面。 扩展仅在单个HTTP / 2连接的范围内有效。

这适用于本文档中定义的协议元素。 这不会影响扩展HTTP的现有选项,例如定义新方法,状态代码或标头字段。

扩展名可以使用新的帧类型(第4.1节),新的设置(第6.5.2节)或新的错误代码(第7节 )。 建立了用于管理这些扩展点的注册表:帧类型(11.2),设置(11.3)和错误代码(11.4) 。

实施必须忽略所有可扩展协议元素中未知或不受支持的值。 实现必须丢弃类型未知或不受支持的帧。 这意味着这些扩展点中的任何一个都可以被扩展安全地使用,而无需事先安排或协商。 但是,不允许出现在标头块(第4.3节)中间的扩展帧。这些必须视为PROTOCOL_ERROR类型的连接错误(第5.4.1节)。

可能会更改现有协议组件语义的扩展必须在使用前进行协商。 例如,在对等端给出一个可接受的肯定信号之前,不能使用更改HEADERS框架布局的扩展名。 在这种情况下,修改后的布局生效时也可能需要进行协调。 请注意,将除DATA帧之外的任何其他帧视为流控制就是这种语义上的更改,并且只能通过协商来完成。

本文档未强制规定使用扩展的具体方法,但请注意,可以将设置(第6.5.2节)用于此目的。 如果两个对等方都设置了一个表示愿意使用该扩展名的值,则可以使用该扩展名。 如果设置用于扩展协商,则必须以初始禁用扩展的方式定义初始值。

6. 帧定义

该规范定义了许多帧类型,每种类型都由唯一的8位类型代码标识。 每种帧类型在整个连接或单个流的建立和管理中都具有不同的目的。

特定帧类型的传输可以更改连接状态。 如果端点无法维护连接状态的同步视图,则将无法再成功进行连接内的通信。 因此,对端点有一个共同的理解,即使用任何给定的帧如何影响状态是很重要的。

6.1. DATA 帧

DATA帧(类型= 0x0)传达与流相关的任意长度可变的八位字节序列。 例如,一个或多个DATA帧用于承载HTTP请求或响应有效负载。

数据帧也可以包含填充。 可以将填充添加到DATA帧,以掩盖消息的大小。 填充是一项安全功能;参见第10.7节

    +---------------+
    |Pad Length? (8)|
    +---------------+-----------------------------------------------+
    |                            Data (*)                         ...
    +---------------------------------------------------------------+
    |                           Padding (*)                       ...
    +---------------------------------------------------------------+
    
                       Figure 6: DATA Frame Payload
    

DATA帧包含以下字段:

Pad Length: 一个8位字段,包含以八位字节为单位的帧填充长度。 该字段是有条件的(在图中用“?”表示),仅当设置了PADDED标志时才存在。

Data: 应用程序数据。 数据量是减去存在的其他字段的长度后剩余的帧有效负载。

Padding: 不包含应用程序语义值的填充字节。 发送时,填充字节必须设置为零。 接收者没有义务验证填充,但可以将非零填充视为PROTOCOL_ERROR类型的连接错误(5.4.1节)。

DATA帧定义以下标志:

END_STREAM(0x1): 设置时,位0指示此帧是端点将为已标识的流发送的最后一个帧。 设置此标志会使流进入“半关闭”状态或“关闭”状态之一(第5.1节)。

PADDED (0x8): 设置时,位3表示存在“填充长度”字段及其描述的任何填充。

数据帧必须与流关联。 如果接收到流标识符字段为0x0的DATA帧,则接收方务必以PROTOCOL_ERROR类型的连接错误(5.4.1节)进行响应。

数据帧受流量控制,并且仅在流处于“打开”或“半关闭(远程)”状态时才能发送。 整个DATA帧有效负载都包含在流控制中,包括填充长度和填充字段(如果存在)。 如果收到的数据帧的流不处于“打开”或“半关闭(本地)”状态,则接收方务必以STREAM_CLOSED类型的流错误(5.4.2)进行响应。

填充字节的总数由“填充长度”字段的值确定。 如果填充的长度是帧有效载荷的长度或更大,则接收者必须将此视为PROTOCOL_ERROR类型的连接错误(5.4.1节)。

注意:通过包含值为零的“填充长度”字段,可以将帧的大小增加一个八位位组。

6.2. HEADERS 帧

HEADERS帧(类型= 0x1)用于打开流(5.1节),并另外携带一个标题块片段。 HEADERS帧可以在“空闲”,“保留(本地)”,“打开”或“半关闭(远程)”状态下在流上发送。

    +---------------+
    |Pad Length? (8)|
    +-+-------------+-----------------------------------------------+
    |E|                 Stream Dependency? (31)                     |
    +-+-------------+-----------------------------------------------+
    |  Weight? (8)  |
    +-+-------------+-----------------------------------------------+
    |                   Header Block Fragment (*)                 ...
    +---------------------------------------------------------------+
    |                           Padding (*)                       ...
    +---------------------------------------------------------------+
    
                      Figure 7: HEADERS Frame Payload
     

HEADERS帧有效负载具有以下字段:

Pad Length:

一个8位字段,包含以八位字节为单位的帧填充长度。 仅当设置了PADDED标志时,此字段才存在。

E:

一位标志,指示流依赖项是互斥的(请参见第5.3部分)。 仅当设置了PRIORITY标志时,此字段才存在。

Stream Dependency:

该流所依赖的流的31位流标识符(请参见第5.3节)。 仅当设置了PRIORITY标志时,此字段才存在。

Weight:

表示流优先级权重的无符号8位整数(请参见第5.3节)。 将值加1可获得1到256之间的权重。 仅当设置了PRIORITY标志时,此字段才存在。

Header Block Fragment:

标头块片段(第4.3部分)。

Padding:

填充八位字节。

HEADERS框架定义以下标志:

END_STREAM(0x1):

设置后,位0指示标头块(第4.3节)是端点为已标识的流发送的最后一个块。

HEADERS帧带有END_STREAM标志,该标志指示流的结束。 但是,设置了END_STREAM标志的HEADERS帧之后可以是同一流上的CONTINUATION帧。 逻辑上,CONTINUATION框架是HEADERS框架的一部分。

END_HEADERS(0x4):

置位时,位2指示该帧包含整个头块(第4.3节),并且之后没有任何CONTINUATION帧。

没有设置END_HEADERS标志的HEADERS帧之后必须是同一流的CONTINUATION帧。 接收者必须将任何其他类型的帧或不同流上的帧的接收视为PROTOCOL_ERROR类型的连接错误(5.4.1节)。

填充(0x8):

设置时,位3表示存在“填充长度”字段及其描述的任何填充。

优先级(0x20):

置位时,位5指示存在独占标志(E),流依赖项和权重字段;参见第5.3节。

HEADERS帧的有效负载包含一个报头块片段(4.3节)。 不适合HEADERS框架的标题块在CONTINUATION框架(第6.10节)中继续。

HEADERS帧必须与流关联。 如果接收到流标识符字段为0x0的HEADERS帧,则接收者务必以PROTOCOL_ERROR类型的连接错误(5.4.1节)进行响应。

HEADERS框架按照4.3节中所述更改连接状态。

HEADERS框架可以包含填充。 填充字段和标志与为DATA帧定义的填充字段和标志相同(第6.1节)。 超出标题块片段剩余大小的填充必须被视为PROTOCOL_ERROR。

HEADERS帧中的优先级信息在逻辑上等效于单独的PRIORITY帧,但是包含在HEADERS中避免了在创建新流时流优先级流失的可能性。 在第一个流之后的HEADERS帧中的优先级字段将对流进行优先级排序(第5.3.3节)。

6.3. PRIORITY 帧

PRIORITY帧(类型= 0x2)指定发送方建议的流优先级(第5.3节)。 它可以在任何流状态下发送,包括空闲或关闭的流。

    +-+-------------------------------------------------------------+
    |E|                  Stream Dependency (31)                     |
    +-+-------------+-----------------------------------------------+
    |   Weight (8)  |
    +-+-------------+
    
                     Figure 8: PRIORITY Frame Payload
    

PRIORITY帧的有效负载包含以下字段:

E:

一位标志,指示流依赖项是互斥的(请参见第5.3部分)。

流依赖性:

该流所依赖的流的31位流标识符(请参见第5.3节)。

Weight:

表示流优先级权重的无符号8位整数(请参见第5.3节)。 将值加1可获得1到256之间的权重。

PRIORITY框架未定义任何标志。

PRIORITY帧始终标识一个流。 如果接收到流标识符为0x0的PRIORITY帧,则接收者务必以PROTOCOL_ERROR类型的连接错误(5.4.1节)进行响应。

尽管不能在包含单个标头块的连续帧之间发送PRIORITY帧,但它可以在任何状态下发送(第4.3节)。 请注意,该帧可能在处理或帧发送完成后到达,这将导致它对标识的流没有影响。 对于处于“半关闭(远程)”或“关闭”状态的流,此帧只能影响所标识的流及其从属流的处理。它不会影响该流上的帧传输。

可以为处于“空闲”或“关闭”状态的流发送PRIORITY帧。 这允许通过更改未使用或关闭的父流的优先级来重新设置一组从属流的优先级。

长度非5个八位位组的优先帧必须被视为类型为FRAME_SIZE_ERROR的流错误(第5.4.2节)。

6.4. RST_STREAM

RST_STREAM帧(类型= 0x3)允许立即终止流。 发送RST_STREAM以请求取消流或指示发生了错误情况。

    +---------------------------------------------------------------+
    |                        Error Code (32)                        |
    +---------------------------------------------------------------+
     
                    Figure 9: RST_STREAM Frame Payload
    

RST_STREAM帧包含一个唯一的无符号32位整数,用于标识错误代码(第7部分)。 错误代码指示为什么终止流。

RST_STREAM帧未定义任何标志。

RST_STREAM帧完全终止引用的流,并使它进入“关闭”状态。 在接收到流上的RST_STREAM之后,接收者必须不发送该流的其他帧,优先级除外。 但是,在发送RST_STREAM之后,发送端点必须准备好接收和处理在RST_STREAM到达之前可能已由对等方发送的流上发送的其他帧。

RST_STREAM帧必须与流关联。 如果收到流标识符为0x0的RST_STREAM帧,则接收者必须将此视为PROTOCOL_ERROR类型的连接错误(5.4.1节)。

对于处于“空闲”状态的流,不得发送RST_STREAM帧。 如果接收到标识空闲流的RST_STREAM帧,则接收者必须将此视为PROTOCOL_ERROR类型的连接错误(5.4.1节)。

长度非4个八位位组的RST_STREAM帧必须被视为FRAME_SIZE_ERROR类型的连接错误(5.4.1节)。

6.5. SETTINGS 帧

SETTINGS帧(类型= 0x4)传达影响端点通信方式的配置参数,例如对等体行为的偏好和约束。 SETTINGS框架还用于确认已接收这些参数。 单独地,SETTINGS参数也可以称为“设置”。

未协商SETTINGS参数;它们描述了发送对等方的特性,接收方使用这些特性。 每个对等体可以通告相同参数的不同值。 例如,客户端可能会设置较高的初始流控制窗口,而服务器可能会设置较低的值以节省资源。

SETTINGS帧必须在连接开始时由两个端点发送,并且在连接的生存期内必须由任一端点在任何其他时间发送。 实现必须支持本规范定义的所有参数。

SETTINGS框架中的每个参数都会替换该参数的任何现有值。 参数按照它们出现的顺序进行处理,并且SETTINGS帧的接收者不需要维护其参数当前值以外的任何状态。 因此,SETTINGS参数的值是接收机看到的最后一个值。

SETTINGS参数由接收对等方确认。 为此,SETTINGS框架定义以下标志:

确认(0x1):

置位时,位0指示此帧确认对等方SETTINGS帧的接收和应用。 当该位置1时,“设置”帧的有效载荷必须为空。 接收到设置有ACK标志且长度字段值不为0的SETTINGS帧时,必须将其视为FRAME_SIZE_ERROR类型的连接错误(5.4.1节)。 有关更多信息,请参见6.5.3节(“设置同步”)。

SETTINGS帧始终应用于连接,而不是单个流。 SETTINGS帧的流标识符必须为零(0x0)。 如果端点接收到流标识符字段不是0x0的SETTINGS帧,则端点必须以PROTOCOL_ERROR类型的连接错误(5.4.1节)进行响应。

SETTINGS框架影响连接状态。 格式错误或不完整的SETTINGS框架必须视为PROTOCOL_ERROR类型的连接错误(第5.4.1节)。

长度不是6个八位字节倍数的SETTINGS帧必须被视为FRAME_SIZE_ERROR类型的连接错误(5.4.1节)。

6.5.1. 设置格式

SETTINGS帧的有效负载包含零个或多个参数,每个参数均包含一个无符号的16位设置标识符和一个无符号的32位值。

    +-------------------------------+
    |       Identifier (16)         |
    +-------------------------------+-------------------------------+
    |                        Value (32)                             |
    +---------------------------------------------------------------+
     
                         Figure 10: Setting Format
    

6.5.2. 定义的设置参数

定义了以下参数:

SETTINGS_HEADER_TABLE_SIZE(0x1):

允许发送方以字节为单位通知远程端点用于解码标头块的标头压缩表的最大大小。 编码器可以通过使用特定于标头块内标头压缩格式的信令来选择等于或小于此值的任何大小(请参见[COMPRESSION])。 初始值为4,096个八位位组。

SETTINGS_ENABLE_PUSH(0x2):

此设置可用于禁用服务器推送(第8.2节)。 如果端点接收到该参数设置为0,则不得发送PUSH_PROMISE帧。 均已将此参数都设置为0并已确认的端点必须将PUSH_PROMISE帧的接收视为PROTOCOL_ERROR类型的连接错误(5.4.1节)。

初始值为1,表示允许服务器推送。 除0或1之外的任何其他值都必须被视为PROTOCOL_ERROR类型的连接错误(第5.4.1节)。

SETTINGS_MAX_CONCURRENT_STREAMS(0x3):

指示发送方允许的最大并发流数。 此限制是有方向的:它适用于发送方允许接收方创建的流的数量。 最初,此值没有限制。 建议该值不小于100,以免不必要地限制并行度。

端点不应将SETTINGS_MAX_CONCURRENT_STREAMS的0值视为特殊值。 零值的确会阻止创建新的流。但是,对于活动流耗尽的任何限制也可能发生这种情况。 服务器应仅在短时间内设置零值;如果服务器不希望接受请求,则关闭连接更为合适。

SETTINGS_INITIAL_WINDOW_SIZE(0x4):

指示用于流级流控制的发送方的初始窗口大小(以八位字节为单位)。 初始值为2 ^ 16-1(65,535)个八位位组。

此设置会影响所有流的窗口大小(请参见第6.9.2节)。

大于最大流量控制窗口大小2 ^ 31-1的值必须视为FLOW_CONTROL_ERROR类型的连接错误(第5.4.1节)。

SETTINGS_MAX_FRAME_SIZE(0x5):

指示发送方愿意接收的最大帧有效负载的大小(以八位字节为单位)。

初始值为2 ^ 14(16,384)个八位位组。 端点通告的值必须在此初始值和允许的最大帧大小(2 ^ 24-1或16,777,215个八位位组)之间(包括此值)。 超出此范围的值必须视为PROTOCOL_ERROR类型的连接错误(第5.4.1节)。

SETTINGS_MAX_HEADER_LIST_SIZE(0x6):

此建议设置以八位字节的形式通知对等端发件人准备接受的报头列表的最大大小。 该值基于标头字段的未压缩大小,包括名称的长度和以八位字节为单位的值,以及每个标头字段的32个八位字节的开销。

对于任何给定的请求,可以强制执行比所公布的更低的限制。 此设置的初始值是无限的。

接收到具有任何未知或不受支持的标识符的SETTINGS帧的端点必须忽略该设置。

6.5.3. 设置同步

SETTINGS中的大多数值都受益于或需要了解对等方何时接收并应用更改后的参数值。 为了提供这样的同步时间点,未设置ACK标志的SETTINGS帧的接收者务必在收到后尽快应用更新后的参数。

SETTINGS帧中的值必须按照它们出现的顺序进行处理,而值之间不得进行其他帧处理。 不支持的参数必须被忽略。 一旦所有值都已处理完毕,接收方务必立即发出设置了ACK标志的SETTINGS帧。 在接收到设置了ACK标志的SETTINGS帧后,更改后的参数的发送方可以依赖于已应用的设置。

如果SETTINGS帧的发送方在合理的时间内未收到确认,则可能会发出SETTINGS_TIMEOUT类型的连接错误(第5.4.1节)。

6.6. PUSH_PROMISE

PUSH_PROMISE帧(类型= 0x5)用于在发送方打算初始化的流之前提前通知对等终结点。 PUSH_PROMISE帧包括端点计划创建的流的无符号31位标识符,以及为流提供附加上下文的一组报头。 第8.2节详细介绍了PUSH_PROMISE帧的使用。

    +---------------+
    |Pad Length? (8)|
    +-+-------------+-----------------------------------------------+
    |R|                  Promised Stream ID (31)                    |
    +-+-----------------------------+-------------------------------+
    |                   Header Block Fragment (*)                 ...
    +---------------------------------------------------------------+
    |                           Padding (*)                       ...
    +---------------------------------------------------------------+
    
                  Figure 11: PUSH_PROMISE Payload Format
     

PUSH_PROMISE帧有效负载具有以下字段:

垫长:

一个8位字段,包含以八位字节为单位的帧填充长度。 仅当设置了PADDED标志时,此字段才存在。

R:

单个保留位。

承诺的流ID:

一个无符号的31位整数,标识PUSH_PROMISE保留的流。 承诺的流标识符必须是发送方发送的下一个流的有效选择(请参见第5.1.1节中的“新流标识符”)。

标头块片段:

包含请求标头字段的标头块片段(第4.3部分)。

填充:

填充八位字节。

PUSH_PROMISE帧定义以下标志:

END_HEADERS(0x4):

置位时,位2指示该帧包含整个头块(第4.3节),并且之后没有任何CONTINUATION帧。

没有设置END_HEADERS标志的PUSH_PROMISE帧之后必须是同一流的CONTINUATION帧。 接收者必须将任何其他类型的帧或不同流上的帧的接收视为PROTOCOL_ERROR类型的连接错误(5.4.1节)。

填充(0x8):

设置时,位3表示存在“填充长度”字段及其描述的任何填充。

PUSH_PROMISE帧只能在处于“打开”或“半关闭(远程)”状态的对等方发起的流上发送。 PUSH_PROMISE帧的流标识符指示与之关联的流。 如果流标识符字段指定值为0x0,则接收方必须以PROTOCOL_ERROR类型的连接错误(5.4.1)进行响应。

不需要按承诺的顺序使用承诺的流。 PUSH_PROMISE仅保留流标识符供以后使用。

如果对等端点的SETTINGS_ENABLE_PUSH设置设为0,则不得发送PUSH_PROMISE。 设置此设置并已收到确认的端点必须将收到PUSH_PROMISE帧视为PROTOCOL_ERROR类型的连接错误(5.4.1节)。

PUSH_PROMISE帧的接收者可以选择将已承诺流标识符返回给RST_STREAM返回给PUSH_PROMISE的发送者,从而拒绝已承诺流。

PUSH_PROMISE帧以两种方式修改连接状态。 首先,包含标头块(第4.3节)可能会修改为标头压缩保留的状态。 其次,PUSH_PROMISE还保留一个流以供以后使用,从而使承诺的流进入“保留”状态。 发件人不得在流上发送PUSH_PROMISE,除非该流是“打开”或“半关闭(远程)”;发送方必须确保承诺的流是新流标识符(第5.1.1节)的有效选择(也就是说,承诺的流必须处于“空闲”状态)。

由于PUSH_PROMISE保留流,因此忽略PUSH_PROMISE帧将导致流状态变得不确定。 接收者必须将在既不是“开放”也不是“半封闭(本地)”的流上收到PUSH_PROMISE视为PROTOCOL_ERROR类型的连接错误(5.4.1节)。 但是,在相关流上发送了RST_STREAM的端点必须处理在接收和处理RST_STREAM帧之前可能已经创建的PUSH_PROMISE帧。

接收者必须将收到的PUSH_PROMISE视为非法类型的连接错误(5.4.1)作为承诺的非法流标识符(5.1.1)作为PROTOCOL_ERROR类型的连接错误。 请注意,非法流标识符是当前不处于“空闲”状态的流的标识符。

PUSH_PROMISE帧可以包含填充。 填充字段和标志与为DATA帧定义的填充字段和标志相同(第6.1节)。

6.7. PING 帧

PING帧(类型= 0x6)是一种机制,用于测量来自发送方的最小往返时间,以及确定空闲连接是否仍然有效。 可以从任何端点发送PING帧。

    +---------------------------------------------------------------+
    |                                                               |
    |                      Opaque Data (64)                         |
    |                                                               |
    +---------------------------------------------------------------+
    
                      Figure 12: PING Payload Format
    

除帧头外,PING帧必须在有效载荷中包含8个八位字节的不透明数据。 发送者可以包括它选择的任何值,并可以任何方式使用这些八位位组。

不包括ACK标志的PING帧的接收者必须发送带有相同有效负载的ACK标志作为响应的PING帧。 应该给PING响应比任何其他帧更高的优先级。

PING帧定义以下标志:

确认(0x1):

置位时,位0指示此PING帧是PING响应。 端点必须在PING响应中设置该标志。 端点不得响应包含该标志的PING帧。

PING帧不与任何单独的流相关联。 如果收到的PING帧的流标识符字段值不是0x0,则接收者务必以PROTOCOL_ERROR类型的连接错误(5.4.1节)进行响应。

收到长度字段值为8以外的PING帧时,必须将其视为FRAME_SIZE_ERROR类型的连接错误(第5.4.1节)。

6.8. GOAWAY 帧

GOAWAY帧(类型= 0x7)用于启动连接关闭或发出严重错误情况信号。 GOAWAY允许端点优雅地停止接受新流,同时仍然完成对先前建立的流的处理。 这将启用管理操作,例如服务器维护。

在端点开始新流和远程发送GOAWAY帧之间存在固有的竞争条件。 为了处理这种情况,GOAWAY包含此连接的发送端点上已处理或可能已处理的最后一个对等方发起的流的流标识符。 例如,如果服务器发送GOAWAY帧,则标识的流是客户端启动的编号最高的流。

一旦发送,如果流的标识符高于所包含的最后一个流标识符,则发送方将忽略在接收方发起的流上发送的帧。 尽管可以为新的流建立新的连接,但GOAWAY帧的接收者不得在连接上打开其他流。

如果GOAWAY的接收器在流标识符发送的数据流比GOAWAY帧中指示的流标识符高的流上发送了数据,则这些流将不会或将不会被处理。 GOAWAY帧的接收器可以将这些流视为从未创建过,因此可以稍后在新连接上重试这些流。

端点应始终在关闭连接之前发送GOAWAY帧,以便远程对等方可以知道流是否已被部分处理。 例如,如果HTTP客户端在服务器关闭连接的同时发送POST,则如果服务器未发送GOAWAY帧来指示其可能具有的流,则客户端将无法知道服务器是否开始处理该POST请求行动了。

端点可能选择关闭连接,而不发送对等端行为不正常的GOAWAY。

GOAWAY框架可能不会立即关闭连接;不再使用该连接的GOAWAY的接收方在终止连接之前仍应发送GOAWAY帧。

    +-+-------------------------------------------------------------+
    |R|                  Last-Stream-ID (31)                        |
    +-+-------------------------------------------------------------+
    |                      Error Code (32)                          |
    +---------------------------------------------------------------+
    |                  Additional Debug Data (*)                    |
    +---------------------------------------------------------------+
    
                     Figure 13: GOAWAY Payload Format
    

GOAWAY框架未定义任何标志。

GOAWAY帧适用于连接,而不是特定的流。 端点必须将流标识符不是0x0的GOAWAY帧视为PROTOCOL_ERROR类型的连接错误(5.4.1节)。

GOAWAY帧中的最后一个流标识符包含编号最高的流标识符,对于该标识符,GOAWAY帧的发送者可能已对其采取了某些措施,或者可能已对其采取了措施。 直至并包括所标识的流的所有流都可能已经以某种方式处理。 如果未处理任何流,则最后一个流标识符可以设置为0。

注意:在这种情况下,“已处理”是指流中的某些数据已传递到可能已采取某些措施的较高软件层。

如果连接在没有GOAWAY帧的情况下终止,则最后一个流标识符实际上是可能的最高流标识符。

在标识符数量较少或相等的流在关闭连接之前没有完全关闭的流上,无法重新尝试请求,事务或任何协议活动,但幂等操作(例如HTTP GET,PUT或DELETE)除外。 可以使用新连接安全地重试使用编号更高的流的任何协议活动。

编号小于或等于最后一个流标识符的流上的活动仍可能成功完成。 GOAWAY帧的发送方可以通过发送GOAWAY帧来正常关闭连接,并保持连接处于“打开”状态,直到所有进行中的流完成为止。

如果情况改变,端点可以发送多个GOAWAY帧。 例如,在正常关闭期间发送NO_ERROR的GOAWAY的端点随后可能会遇到需要立即终止连接的情况。 来自接收到的最后一个GOAWAY帧的最后一个流标识符表示哪些流可能已作用。 端点不得增加它们在最后一个流标识符中发送的值,因为对等点可能已经在另一个连接上重试了未处理的请求。

当服务器关闭连接时,无法重试请求的客户端将丢失所有正在处理的请求。 对于可能不使用HTTP / 2为客户端提供服务的中介尤其如此。 尝试正常关闭连接的服务器应发送初始GOAWAY帧,其最后一个流标识符设置为2 ^ 31-1,并提供NO_ERROR代码。 这向客户端发出信号,即将关闭,并且禁止发起进一步的请求。 在允许有任何进行中的流创建时间(至少一个往返时间)之后,服务器可以发送具有更新的最后一个流标识符的另一个GOAWAY帧。 这确保可以干净地关闭连接而不会丢失请求。

发送GOAWAY帧后,发送方可以丢弃接收方发起的流的帧,这些流的标识符要比所标识的最后一个流高。 但是,任何更改连接状态的帧都不能完全忽略。 例如,必须最少处理HEADERS,PUSH_PROMISE和CONTINUATION帧,以确保为报头压缩保持的状态是一致的(请参见4.3节);类似地,必须将DATA帧计入连接流控制窗口。 无法处理这些帧可能导致流控制或头压缩状态变得不同步。

GOAWAY框架还包含一个32位错误代码(第7部分),其中包含关闭连接的原因。

端点可以将不透明数据附加到任何GOAWAY帧的有效载荷上。 其他调试数据仅用于诊断目的,不包含语义值。 调试信息可能包含对安全性或隐私敏感的数据。 记录或以其他方式持久存储的调试数据务必具有足够的防护措施,以防止未经授权的访问。

6.9. WINDOW_UPDATE

WINDOW_UPDATE帧(类型= 0x8)用于实现流控制;有关概述,请参见第5.2节。

流控制在两个级别上运行:在每个单独的流上以及在整个连接上。

两种类型的流控制都是逐跳的,即仅在两个端点之间。 中介程序不转发依赖连接之间的WINDOW_UPDATE帧。 但是,任何接收者进行的数据传输限制都可能间接导致流控制信息向原始发送者传播。

流控制仅适用于被标识为受流控制的帧。 在本文档中定义的帧类型中,这仅包括DATA帧。 除非接收者无法分配资源来处理帧,否则必须接受和处理不受流量控制的帧。 如果接收器无法接受帧,则可能以FLOW_CONTROL_ERROR类型的流错误(5.4.2)或连接错误(5.4.1)进行响应。

    +-+-------------------------------------------------------------+
    |R|              Window Size Increment (31)                     |
    +-+-------------------------------------------------------------+
    
                  Figure 14: WINDOW_UPDATE Payload Format
    

WINDOW_UPDATE帧的有效负载是一个保留位加上一个无符号的31位整数,该整数指示发送者除了现有的流控制窗口之外还可以发送的八位字节数。 流量控制窗口增量的合法范围是1到2 ^ 31-1(2,147,483,647)个八位位组。

WINDOW_UPDATE框架未定义任何标志。

WINDOW_UPDATE帧可以特定于流或整个连接。 在前一种情况下,帧的流标识符指示受影响的流;在后者中,值“ 0”指示整个连接是框架的主题。

接收方务必将流控制窗口增量为0的WINDOW_UPDATE帧的接收视为PROTOCOL_ERROR类型的流错误(5.4.2节);连接流控制窗口上的错误必须视为连接错误(5.4.1节)。

可以由已发送带有END_STREAM标志的帧的对等方发送WINDOW_UPDATE。 这意味着接收器可以在“半封闭(远程)”或“封闭”流上接收WINDOW_UPDATE帧。 接收者不得将此视为错误(请参见第5.1节)。

接收到流控制帧的接收者必须始终考虑其对连接流控制窗口的贡献,除非接收者将其视为连接错误(5.4.1节)。 即使框架有错误,这也是必要的。 发送方朝着流控制窗口计数帧,但是如果接收方没有,则发送方和接收方的流控制窗口可能会不同。

长度非4个八位位组的WINDOW_UPDATE帧必须被视为FRAME_SIZE_ERROR类型的连接错误(第5.4.1节)。

6.9.1. 流控制窗口

HTTP / 2中的流控制使用每个发送者在每个流上保留的窗口来实现。 流量控制窗口是一个简单的整数值,指示允许发送方传输多少个八位位组的数据;因此,它的大小是接收器缓冲能力的度量。

可应用两个流量控制窗口:流流量控制窗口和连接流量控制窗口。 发送方不得发送长度超过接收方通告的任何一个流控制窗口中可用空间的流控制帧。 如果两个流控制窗口中都没有可用空间,则可以发送长度为零且设置了END_STREAM标志的帧(即,空的DATA帧)。

对于流控制计算,不计9个字节的帧头。

发送流控制的帧后,发送方将两个窗口中的可用空间减小所发送帧的长度。

帧的接收者发送WINDOW_UPDATE帧,因为它消耗数据并释放流控制窗口中的空间。 为流级别和连接级别的流控制窗口发送单独的WINDOW_UPDATE帧。

接收到WINDOW_UPDATE框架的发送方将按照框架中指定的数量更新相应的窗口。

发送者必须不允许流量控制窗口超过2 ^ 31-1个八位位组。 如果发送方收到WINDOW_UPDATE导致流控制窗口超过此最大值,则它必须视情况终止流或连接。 对于流,发送方发送带有错误代码FLOW_CONTROL_ERROR的RST_STREAM;对于连接,将发送错误代码为FLOW_CONTROL_ERROR的GOAWAY帧。

来自发送器的流控制帧和来自接收器的WINDOW_UPDATE帧彼此完全异步。 此属性允许接收方积极更新发送方保留的窗口大小,以防止流停止。

6.9.2. 初始流控制窗口大小

首次建立HTTP / 2连接时,将创建初始流控制窗口大小为65,535个八位位组的新流。 连接流控制窗口也是65,535个八位位组。 两个端点都可以通过在构成连接前言一部分的SETTINGS帧中包含SETTINGS_INITIAL_WINDOW_SIZE的值来调整新流的初始窗口大小。 只能使用WINDOW_UPDATE框架更改连接流控制窗口。

在接收为SETTINGS_INITIAL_WINDOW_SIZE设置值的SETTINGS帧之前,端点在发送流控制的帧时只能使用默认的初始窗口大小。 同样,将连接流控制窗口设置为默认的初始窗口大小,直到接收到WINDOW_UPDATE帧为止。

除了更改尚未激活的流的流控制窗口外,SETTINGS框架还可以更改具有活动流控制窗口的流(即“打开”或“一半”中的流)的初始流控制窗口大小。 -closed(远程)”状态)。 当SETTINGS_INITIAL_WINDOW_SIZE的值更改时,接收方务必通过新值和旧值之间的差来调整其所维护的所有流流控制窗口的大小。

对SETTINGS_INITIAL_WINDOW_SIZE的更改可能导致流控制窗口中的可用空间变为负数。 发送方必须跟踪否定的流控制窗口,并且不得发送新的流控制的帧,直到其接收到导致流控制窗口变为正的WINDOW_UPDATE帧。

例如,如果客户端在建立连接后立即发送60 KB,并且服务器将初始窗口大小设置为16 KB,则客户端将在收到SETTINGS帧后重新计算可用的流控制窗口为-44 KB。 客户端将保留否定的流控制窗口,直到WINDOW_UPDATE帧将窗口恢复为正,然后客户端才能继续发送。

SETTINGS框架无法更改连接流控制窗口。

端点必须将对SETTINGS_INITIAL_WINDOW_SIZE的更改视为任何导致流控制窗口超过最大大小的更改视为FLOW_CONTROL_ERROR类型的连接错误(5.4.1节)。

6.9.3. 减少流窗口大小

希望使用比当前大小小的流控制窗口的接收器可以发送新的SETTINGS帧。 但是,接收者必须准备接收超过该窗口大小的数据,因为发送者可能在处理SETTINGS帧之前发送了超过下限的数据。

发送减小初始流控制窗口大小的SETTINGS帧后,接收机可以继续处理超出流控制限制的流。 允许流继续运行不会使接收器立即减少其为流控制窗口保留的空间。 这些流上的进度也可能会停止,因为需要WINDOW_UPDATE帧来允许发送方恢复发送。 接收者可以向受影响的流发送RST_STREAM,错误代码为FLOW_CONTROL_ERROR。

6.10. 持续性

CONTINUATION帧(类型= 0x9)用于继续一系列头块片段(4.3节)。 只要前一帧在同一流上并且是没有设置END_HEADERS标志的HEADERS,PUSH_PROMISE或CONTINUATION帧,就可以发送任意数量的CONTINUATION帧。

    +---------------------------------------------------------------+
    |                   Header Block Fragment (*)                 ...
    +---------------------------------------------------------------+
    
                   Figure 15: CONTINUATION Frame Payload
    

CONTINUATION帧有效载荷包含一个头块片段(第4.3节)。

CONTINUATION框架定义以下标志:

END_HEADERS(0x4):

置位时,位2指示该帧结束头块(第4.3节)。

如果未设置END_HEADERS位,则此帧之后必须跟另一个CONTINUATION帧。 接收者必须将任何其他类型的帧或不同流上的帧的接收视为PROTOCOL_ERROR类型的连接错误(5.4.1节)。

CONTINUATION框架按照4.3节中的定义更改连接状态。

连续帧必须与流关联。 如果接收到流标识符字段为0x0的CONTINUATION帧,则接收者务必以PROTOCOL_ERROR类型的连接错误(5.4.1节)进行响应。

没有设置END_HEADERS标志的HEADERS,PUSH_PROMISE或CONTINUATION帧必须在CONTINUATION帧之前。 观察到违反此规则的收件人必须以PROTOCOL_ERROR类型的连接错误(第5.4.1节)进行响应。

7. 错误代码

错误代码是32位字段,用于RST_STREAM和GOAWAY帧中,以传达流或连接错误的原因。

错误代码共享一个公共代码空间。 一些错误代码仅适用于流或整个连接,而在其他上下文中没有定义的语义。

定义了以下错误代码:

NO_ERROR(0x0):

相关条件不是错误的结果。 例如,GOAWAY可能包含此代码以指示正常关闭连接。

PROTOCOL_ERROR(0x1):

端点检测到非特定协议错误。 当没有更特定的错误代码时,将使用此错误。

INTERNAL_ERROR (0x2):

端点遇到意外的内部错误。

FLOW_CONTROL_ERROR(0x3):

端点检测到其对等方违反了流控制协议。

SETTINGS_TIMEOUT(0x4):

端点发送了一个SETTINGS帧,但是没有及时收到响应。 请参见第6.5.3节(“设置同步”)。

STREAM_CLOSED(0x5):

流半关闭后,端点接收到一帧。

FRAME_SIZE_ERROR(0x6):

端点收到的帧大小无效。

REFUSED_STREAM(0x7):

端点在执行任何应用程序处理之前拒绝了该流(有关详细信息,请参见第8.1.4节)。

CANCEL (0x8):

端点使用它来指示不再需要该流。

COMPRESSION_ERROR(0x9):

端点无法维护连接的头压缩上下文。

CONNECT_ERROR(0xa):

响应CONNECT请求(第8.3节)而建立的连接被重置或异常关闭。

ENHANCE_YOUR_CALM(0xb):

端点检测到其对等方正在表现出可能会产生过多负载的行为。

INADEQUATE_SECURITY(0xc):

基础传输具有不满足最低安全要求的属性(请参见第9.2节)。

HTTP_1_1_REQUIRED(0xd):

端点要求使用HTTP / 1.1代替HTTP / 2。

未知或不受支持的错误代码不得触发任何特殊行为。 实现可以将它们视为等同于INTERNAL_ERROR。

8. HTTP 消息交换

HTTP / 2旨在与HTTP的当前使用尽可能兼容。 这意味着,从应用程序角度来看,该协议的功能在很大程度上没有变化。 为此,尽管传达这些语义的语法已更改,但保留了所有请求和响应语义。

因此,HTTP / 1.1语义和内容[RFC7231],条件请求[RFC7232],范围请求[RFC7233]的规范和要求,缓存[RFC7234]和身份验证[RFC7235]适用于HTTP / 2。 HTTP / 1.1消息语法和路由[RFC7230]的选定部分,例如HTTP和HTTPS URI方案,也适用于HTTP / 2,但是该协议的那些语义的表达在以下各节。

8.1. HTTP 请求/响应交换

客户端使用先前未使用的流标识符(第5.1.1节)在新流上发送HTTP请求。 服务器在与请求相同的流上发送HTTP响应。

HTTP消息(请求或响应)包括:

1. 仅用于响应,包含信息性(1xx)HTTP响应的消息头的零个或多个HEADERS帧(每个后跟零个或多个CONTINUATION帧)(请参阅[RFC7230],第3.2节 t1” >和[RFC7231],第6.2),

2. 一个包含消息头的HEADERS帧(后跟零个或多个CONTINUATION帧)(请参阅[RFC7230],第3.2节)

3. 零个或多个包含有效载荷主体的DATA帧(请参阅[RFC7230],第3.3节)和

4. (可选)一个HEADERS帧,后跟零个或多个包含尾部的CONTINUATION帧(如果有的话)(请参阅[RFC7230],第4.1.2节)。

序列中的最后一个帧带有END_STREAM标志,请注意,带有END_STREAM标志的HEADERS帧之后可以跟随CONTINUATION帧,这些帧携带了头块的其余部分。

其他帧(来自任何流)不得在HEADERS帧和随后的任何CONTINUATION帧之间出现。

HTTP / 2使用DATA帧来承载消息有效负载。 [RFC7230]的4.1节中定义的“块状”传输编码务必不能在HTTP / 2中使用。

尾标头字段携带在标头块中,该标头块也终止流。 这样的标题块是从HEADERS帧开始的序列,然后是零个或多个CONTINUATION帧,其中HEADERS帧带有END_STREAM标志。 第一个之后的不终止流的头块不属于HTTP请求或响应。

HEADERS框架(和关联的CONTINUATION框架)只能出现在流的开头或结尾。 在接收到最终的(非信息性的)状态码后,接收到没有设置END_STREAM标志的HEADERS帧的端点,必须将相应的请求或响应视为格式错误(8.1.2.6节)。

HTTP请求/响应交换完全消耗单个流。 请求从HEADERS帧开始,该帧将流置于“打开”状态。 该请求以带有END_STREAM的帧结束,该帧使流对于客户端变为“半关闭(本地)”,对于服务器变为“半关闭(远程)”。 响应以HEADERS帧开始,以带有END_STREAM的帧结束,该帧将流置于“关闭”状态。

服务器发送(或客户端接收)设置了END_STREAM标志的帧(包括完成标头块所需的任何CONTINUATION帧)后,HTTP响应完成。 如果响应不依赖于尚未发送和接收的请求的任何部分,则服务器可以在客户端发送整个请求之前发送完整的响应。 如果为真,则服务器可以在发送完整的响应(即带有END_STREAM标志的帧)后发送错误代码为RST_STREAM的RST_STREAM来请求客户端中止请求的发送而不会出错。 客户端不得由于收到这样的RST_STREAM而丢弃响应,尽管客户端出于其他原因始终可以自行决定是否丢弃响应。

8.1.1. 从HTTP / 2升级

HTTP / 2删除了对101(交换协议)信息状态代码([RFC7231],第6.2.2部分)的支持。

101(交换协议)的语义不适用于多路复用协议。 替代协议可以使用与HTTP / 2协商使用相同的机制(请参见第3节)。

8.1.2. HTTP标头字段

HTTP标头字段将信息作为一系列键值对携带。 For a listing of registered HTTP headers, see the "Message Header Field" registry maintained at <https://www.iana.org/assignments/ message-headers>.

与HTTP / 1.x中一样,标头字段名称是ASCII字符的字符串,以不区分大小写的方式进行比较。 但是,报头字段名称必须先转换为小写,然后再使用HTTP / 2进行编码。 包含大写标头字段名称的请求或响应必须被视为格式错误(第8.1.2.6节)。

8.1.2.1. 伪头字段

HTTP / 1.x使用消息起始行(请参见[RFC7230],第3.1节)来传达目标URI,请求的方法以及响应的状态代码,HTTP /为此,2使用特殊的伪头字段,以':'字符(ASCII 0x3a)开头。

伪头字段不是HTTP头字段。 端点不得生成除本文档中定义的字段以外的伪标题字段。

伪标题字段仅在定义它们的上下文中有效。 为请求定义的伪标题字段不得出现在响应中;为响应定义的伪标题字段不得出现在请求中。 伪标题字段不得出现在预告片中。 端点必须将包含未定义或无效伪报头字段的请求或响应视为格式错误(第8.1.2.6节)。

所有伪标头字段必须出现在标头块中常规标头字段之前。 在常规标头字段之后出现在标头块中的任何包含伪标头字段的请求或响应都必须被视为格式错误(第8.1.2.6节)。

8.1.2.2. 特定于连接的标题字段

HTTP / 2不使用Connection标头字段来指示特定于连接的标头字段;在此协议中,特定于连接的元数据通过其他方式传达。 端点不得生成包含特定于连接的报头字段的HTTP / 2消息;任何包含特定于连接的报头字段的消息都必须被视为格式错误(第8.1.2.6节)。

唯一的例外是TE标头字段,该字段可以出现在HTTP / 2请求中。如果是,则除“ trailers”外,不得包含其他任何值。

这意味着将HTTP / 1.x消息转换为HTTP / 2的中介程序将需要删除由Connection标头字段指定的所有标头字段,以及Connection标头字段本身。 这样的中介也应该删除其他特定于连接的头字段,例如Keep-Alive,Proxy-Connection,Transfer-Encoding和Upgrade,即使它们不是由Connection头字段指定的。

注意:HTTP / 2有意不支持升级到另一个协议。 人们认为第3节中描述的握手方法足以协商使用替代协议。

8.1.2.3. 请求伪标题字段

为HTTP / 2请求定义了以下伪头字段:

o “:method”伪标题字段包括HTTP方法([RFC7231],第4节)。

o “:scheme”伪标题字段包括目标URI的方案部分([RFC3986],第3.1节)。

“:scheme”不仅限于“ http”和“ https”计划的URI。 代理或网关可以转换对非HTTP方案的请求,从而可以使用HTTP与非HTTP服务进行交互。

o “:authority”伪标题字段包括目标URI的权限部分([RFC3986],第3.2节)。 权限不得包含针对“ http”或“ https”方案URI弃用的“ userinfo”子组件。

为了确保可以正确再现HTTP / 1.1请求行,当从具有源或星号形式的请求目标的HTTP / 1.1请求进行转换时,必须忽略此伪标头字段(请参见[RFC7230] 5.3)。 直接产生HTTP / 2请求的客户端应该使用“:authority”伪头字段而不是主机头字段。 如果请求中不存在一个将HTTP / 2请求转换为HTTP / 1.1的中介,则必须通过复制“:authority”伪头字段的值来创建主机头字段。

o “:path”伪标题字段包括目标URI的路径和查询部分(“绝对路径”生产以及可选的“?”字符,后跟“查询”生产(请参见3.3 t0>和[RFC3986]的3.4)。 星号形式的请求包括“:path”伪标题字段的值“ *”。

对于“ http”或“ https” URI,此伪标题字段不得为空;不包含路径组件的“ http”或“ https” URI必须包含“ /”值。 此规则的例外是对不包含路径组件的“ http”或“ https” URI的OPTIONS请求;这些必须包含一个值为“ *”的“:path”伪标题字段(请参见[RFC7230],第5.3.4节)。

所有HTTP / 2请求都必须为“:method”,“:scheme”和“:path”伪头字段仅包含一个有效值,除非它是CONNECT请求(第8.3节) 。 忽略必需的伪头字段的HTTP请求格式错误(第8.1.2.6节)。

HTTP / 2没有定义一种方式来携带HTTP / 1.1请求行中包含的版本标识符。

8.1.2.4. 响应伪头字段

对于HTTP / 2响应,定义了一个单独的“:status”伪头字段,该字段带有HTTP状态代码字段(请参见[RFC7231],第6部分)。 该伪报头字段必须包含在所有响应中;否则,响应格式不正确(第8.1.2.6节)。

HTTP / 2没有定义一种方式来携带HTTP / 1.1状态行中包含的版本或原因短语。

8.1.2.5. 压缩Cookie标头字段

Cookie标题字段[COOKIE]使用分号(“;”)来分隔Cookie对(或“小块”)。 此标头字段不遵循HTTP中的列表构造规则(请参阅[RFC7230],第3.2.2部分),该规则可防止将cookie对分离为不同的名称/值对。 随着各个Cookie对的更新,这会大大降低压缩效率。

为了获得更好的压缩效率,Cookie头字段可以分成单独的头字段,每个头字段具有一个或多个cookie对。 如果解压缩后有多个Cookie头字段,则必须在将它们传递到非HTTP / 2上下文之前使用0x3B,0x20的两个八位字节定界符(ASCII字符串“;”)将它们串联为一个八位字节字符串。作为HTTP / 1.1连接或通用HTTP服务器应用程序。

因此,以下两个Cookie标头字段列表在语义上是等效的。

     cookie: a=b; c=d; e=f
    
     cookie: a=b
     cookie: c=d
     cookie: e=f
    
8.1.2.6. 格式错误的请求和响应

格式错误的请求或响应是一个HTTP / 2帧的有效序列,但由于存在多余的帧,禁止的标头字段,缺少必需的标头字段或包含大写的标头字段名称,因此无效。

包括有效载荷主体的请求或响应可以包括内容长度标头字段。 如果内容长度标头字段的值不等于构成主体的DATA帧有效载荷长度的总和,则请求或响应也将格式错误。 [RFC7230]第3.3.2节中所述,定义为没有有效负载的响应可以具有非零的内容长度标头字段,即使DATA帧中不包含任何内容。

处理HTTP请求或响应的中介(即,任何不充当隧道的中介)不得转发格式错误的请求或响应。 检测到格式错误的请求或响应必须视为PROTOCOL_ERROR类型的流错误(5.4.2节)。

对于格式错误的请求,服务器可以在关闭或重置流之前发送HTTP响应。 客户不得接受格式错误的回复。 请注意,这些要求旨在防止针对HTTP的几种常见攻击。它们刻意严格,因为放任其可将实现暴露给这些漏洞。

8.1.3. 例子

本节显示HTTP / 1.1请求和响应,并说明等效的HTTP / 2请求和响应。

HTTP GET请求包括请求标头字段而没有有效载荷主体,因此,将其作为单个HEADERS帧发送,随后是零个或多个包含请求标头字段序列化块的CONTINUATION帧。 下面的HEADERS框架同时设置了END_HEADERS和END_STREAM标志;没有发送连续帧。

     GET /resource HTTP/1.1           HEADERS
     Host: example.org          ==>     + END_STREAM
     Accept: image/jpeg                 + END_HEADERS
                                          :method = GET
                                          :scheme = https
                                          :path = /resource
                                          host = example.org
                                          accept = image/jpeg

    

同样,仅包含响应头字段的响应将作为包含响应头字段序列化块的HEADERS帧(再次是零个或多个CONTINUATION帧)进行传输。

     HTTP/1.1 304 Not Modified        HEADERS
     ETag: "xyzzy"              ==>     + END_STREAM
     Expires: Thu, 23 Jan ...           + END_HEADERS
                                          :status = 304
                                          etag = "xyzzy"
                                          expires = Thu, 23 Jan ...
    

包含请求标头字段和有效负载数据的HTTP POST请求将作为一个HEADERS帧传输,随后是包含请求标头字段的零个或多个CONTINUATION帧,然后是一个或多个DATA帧,最后一个CONTINUATION(或HEADERS)帧具有设置END_HEADERS标志,并设置END_STREAM标志的最终数据帧:

     POST /resource HTTP/1.1          HEADERS
     Host: example.org          ==>     - END_STREAM
     Content-Type: image/jpeg           - END_HEADERS
     Content-Length: 123                  :method = POST
                                          :path = /resource
     {binary data}                        :scheme = https

                                      CONTINUATION
                                        + END_HEADERS
                                          content-type = image/jpeg
                                          host = example.org
                                          content-length = 123

                                      DATA
                                        + END_STREAM
                                      {binary data}

    

注意,有助于任何给定标题字段的数据可以在标题块片段之间散布。 在该示例中,头字段到帧的分配仅是说明性的。

包含标头字段和有效载荷数据的响应将作为HEADERS帧,随后零个或多个CONTINUATION帧,随后一个或多个DATA帧进行传输,序列中的最后一个DATA帧设置了END_STREAM标志:

     HTTP/1.1 200 OK                  HEADERS
     Content-Type: image/jpeg   ==>     - END_STREAM
     Content-Length: 123                + END_HEADERS
                                          :status = 200
     {binary data}                        content-type = image/jpeg
                                          content-length = 123

                                      DATA
                                        + END_STREAM
                                      {binary data}
    

使用除101以外的1xx状态码的信息响应作为HEADERS帧传输,后跟零个或多个CONTINUATION帧。

在请求或响应标头块以及所有DATA帧都已发送之后,尾部标头字段作为标头块发送。 开始于拖车标题块的HEADERS帧设置了END_STREAM标志。

下面的示例包含一个100(继续)状态码和尾随头字段,该状态码是响应于在Expect头字段中包含“ 100-continue”令牌的请求而发送的:

     HTTP/1.1 100 Continue            HEADERS
     Extension-Field: bar       ==>     - END_STREAM
                                        + END_HEADERS
                                          :status = 100
                                          extension-field = bar

     HTTP/1.1 200 OK                  HEADERS
     Content-Type: image/jpeg   ==>     - END_STREAM
     Transfer-Encoding: chunked         + END_HEADERS
     Trailer: Foo                         :status = 200
                                          content-length = 123
     123                                  content-type = image/jpeg
     {binary data}                        trailer = Foo
     0
     Foo: bar                         DATA
                                        - END_STREAM
                                      {binary data}

                                      HEADERS
                                        + END_STREAM
                                        + END_HEADERS
                                          foo = bar

     

8.1.4. HTTP / 2中的请求可靠性机制

在HTTP / 1.1中,发生错误时,HTTP客户端无法重试非幂等请求,因为无法确定错误的性质。 可能在错误之前发生了一些服务器处理,如果重新尝试了该请求,可能导致不良后果。

HTTP / 2提供了两种机制来向客户端保证请求尚未处理:

o GOAWAY帧指示可能已处理的最高流编号。 因此,可以保证对具有更高编号的流的请求可以安全地重试。

o REFUSED_STREAM错误代码可以包含在RST_STREAM帧中,以指示在进行任何处理之前已关闭流。 可以安全地重试在重置流上发送的任何请求。

未处理的请求没有失败;客户端可以自动重试,即使那些使用非幂等方法的客户端。

服务器除非可以保证事实,否则不得指示未处理流。 如果流上的帧被传递给任何流的应用层,则REFUSED_STREAM不得用于该流,并且GOAWAY帧必须包括大于或等于给定流标识符的流标识符。

除了这些机制之外,PING框架还为客户端提供了一种轻松测试连接的方法。 由于某些中间盒(例如,网络地址转换器或负载平衡器)静默丢弃连接绑定,因此保持空闲状态的连接可能会断开。 PING框架允许客户端在不发送请求的情况下安全地测试连接是否仍处于活动状态。

8.2. 服务器推送

HTTP / 2允许服务器与先前的客户端发起的请求相关联地抢先向客户端发送(或“推送”)响应(以及相应的“承诺”请求)。 当服务器知道客户端需要使这些响应可用以完全处理对原始请求的响应时,此功能很有用。

客户端可以请求禁用服务器推送,尽管这是针对每个跃点单独协商的。 可以将SETTINGS_ENABLE_PUSH设置设置为0,以指示禁用服务器推送。

承诺的请求必须是可缓存的(请参阅[RFC7231],第4.2.3节),必须是安全的(请参见[RFC7231],第4.2.1节),并且不得包含请求正文。 收到无法缓存的承诺请求,未知安全性或表明存在请求主体的客户端务必用流错误重置承诺流(5.4.2节)类型为PROTOCOL_ERROR。 请注意,如果客户端未将新定义的方法视为安全方法,则可能导致重置承诺的流。

如果客户端实现了HTTP缓存,则可以存储可缓存的推送响应(请参阅[RFC7234],第3节)。 推送的响应被认为在原始服务器上已成功验证(例如,如果存在“ no-cache”缓存响应指令([RFC7234],第5.2.2节)),则由承诺的流标识流ID仍处于打开状态。

不可缓存的推送响应绝不能由任何HTTP缓存存储。 它们可以单独提供给应用程序。

服务器必须在服务器授权的“:authority”伪头字段中包含一个值(请参见第10.1节)。 客户端必须将服务器不具有权威性的PUSH_PROMISE视为PROTOCOL_ERROR类型的流错误(5.4.2节)。

中介可以从服务器接收推送,并选择不将其转发到客户端。 换句话说,如何利用推送的信息取决于该中介。 同样,中介可能会选择对客户端进行其他推送,而服务器不会采取任何措施。

客户端无法推送。 因此,服务器必须将收到PUSH_PROMISE帧视为PROTOCOL_ERROR类型的连接错误(第5.4.1节)。 客户端必须通过将消息视为PROTOCOL_ERROR类型的连接错误(第5.4.1节)来拒绝任何将SETTINGS_ENABLE_PUSH设置更改为0以外的值的尝试。

8.2.1. 推送请求

服务器推送在语义上等效于服务器响应请求。但是,在这种情况下,该请求也由服务器作为PUSH_PROMISE帧发送。

PUSH_PROMISE帧包括一个标头块,该标头块包含服务器将属性分配给请求的完整的请求标头字段集。 无法将响应推送到包含请求正文的请求。

推送响应始终与客户端的显式请求关联。 服务器发送的PUSH_PROMISE帧在该显式请求的流上发送。 PUSH_PROMISE帧还包括从服务器可用的流标识符中选择的承诺流标识符(请参阅第5.1.1节)。

PUSH_PROMISE中的标头字段和任何后续的CONTINUATION帧必须是一组有效且完整的请求标头字段(第8.1.2.3节)。 服务器必须在“:method”伪标题字段中包含安全且可缓存的方法。 如果客户端收到的PUSH_PROMISE不包含完整且有效的头字段集,或者“:method”伪头字段标识了不安全的方法,则它必须以流错误响应(第5.4节。 2),类型为PROTOCOL_ERROR。

在发送任何引用承诺响应的帧之前,服务器应该发送PUSH_PROMISE(第6.6)帧。 这避免了客户端在接收任何PUSH_PROMISE帧之前发出请求的竞争。

例如,如果服务器收到包含包含指向多个图像文件的嵌入式链接的文档的请求,并且服务器选择将这些其他图像推送到客户端,则在包含图像链接的DATA帧之前发送PUSH_PROMISE帧可确保客户端能够在发现嵌入式链接之前先查看将要推送的资源。 同样,如果服务器推送标题块引用的响应(例如,在“链接”标题字段中),则在发送标题块之前发送PUSH_PROMISE可以确保客户端不请求这些资源。

客户端不得发送PUSH_PROMISE帧。

服务器可以响应任何客户端启动的流发送PUSH_PROMISE帧,但是相对于服务器,该流必须处于“打开”或“半关闭(远程)”状态。 尽管PUSH_PROMISE帧无法与组成单个报头块的HEADERS和CONTINUATION帧交错,但它们仍包含构成响应的帧。

发送PUSH_PROMISE帧将创建一个新流,并将该流置于服务器的“保留(本地)”状态,以及客户机的“保留(远程)”状态。

8.2.2. 推送响应

发送PUSH_PROMISE帧之后,服务器可以开始在服务器上使用承诺的流标识符的流上传递推送的响应作为响应(第8.1.2.4节)。 服务器使用与第8.1节中定义的帧序列相同的帧序列,使用此流传输HTTP响应。 发送初始HEADERS帧后,此流对客户端(第5.1部分)“关闭”。

一旦客户端接收到PUSH_PROMISE帧并选择接受推送的响应,则在承诺流关闭之前,客户端不应该发出任何对承诺响应的请求。

如果客户端出于某种原因确定不希望从服务器接收推送的响应,或者服务器花费太长时间来开始发送承诺的响应,则客户端可以使用CANCEL或REFUSED_STREAM发送RST_STREAM帧代码并引用推送的流的标识符。

客户端可以使用SETTINGS_MAX_CONCURRENT_STREAMS设置来限制服务器可以同时推送的响应数。 公布SETTINGS_MAX_CONCURRENT_STREAMS值为零将阻止服务器创建必要的流,从而禁用服务器推送。 这并不禁止服务器发送PUSH_PROMISE帧。客户端需要重置所有不需要的流。

接收到推送响应的客户端必须验证服务器是权威服务器(请参见10.1)还是为相应请求配置了推送响应的代理。 例如,不允许仅针对“ example.com” DNS-ID或通用名称提供证书的服务器推送对“ https://www.example.org/doc”的响应。

对于PUSH_PROMISE流的响应以HEADERS帧开始,该帧立即将流置于服务器的“半关闭(远程)”状态和客户端的“半关闭(本地)”状态,并以一帧结束承载END_STREAM,将流置于“关闭”状态。

注意:客户端永远不会发送带有END_STREAM标志的帧以进行服务器推送。

8.3. CONNECT方法

在HTTP / 1.x中,伪方法CONNECT([RFC7231],第4.3.6节)用于将HTTP连接转换为通往远程主机的隧道。 CONNECT主要与HTTP代理一起使用,以与源服务器建立TLS会话,以便与“ https”资源进行交互。

在HTTP / 2中,出于类似目的,CONNECT方法用于在单个HTTP / 2流上建立到远程主机的隧道。 HTTP标头字段映射按第8.1.2.3节(“请求伪标头字段”)中的定义进行操作,但有一些区别。 特别:

o “:method”伪标题字段设置为“ CONNECT”。

o 必须省略“:scheme”和“:path”伪标题字段。

o “:authority”伪标题字段包含要连接的主机和端口(相当于CONNECT请求的请求目标的授权形式(请参见[RFC7230],第5.3部分))。

不符合这些限制的CONNECT请求格式错误(第8.1.2.6节)。

支持CONNECT的代理建立与“:authority”伪头字段中标识的服务器的TCP连接[TCP]。 成功建立此连接后,代理将按照[RFC7231]第4.3.6节中的定义,将包含2xx系列状态代码的HEADERS帧发送给客户端。

在每个对等方发送初始HEADERS帧之后,所有后续DATA帧都对应于在TCP连接上发送的数据。 客户端发送的任何DATA帧的有效载荷都由代理服务器传输到TCP服务器。从TCP服务器接收的数据由代理组装为DATA帧。 DATA或流管理帧以外的帧类型(RST_STREAM,WINDOW_UPDATE和PRIORITY)不得在已连接的流上发送,如果收到,则必须视为流错误(5.4.2节)。

任一对等方均可关闭TCP连接。 DATA帧上的END_STREAM标志被视为等效于TCP FIN位。 希望客户端在接收到带有END_STREAM标志的帧后发送设置了END_STREAM标志的DATA帧。 接收到设置了END_STREAM标志的DATA帧的代理将在最后一个TCP段上将FIN位置1的附件数据发送出去。 接收到设置了FIN位的TCP段的代理将发送设置了END_STREAM标志的DATA帧。 请注意,最后的TCP段或DATA帧可能为空。

RST_STREAM指示TCP连接错误。 代理将TCP连接中的任何错误(包括接收到设置有RST位的TCP段)视为CONNECT_ERROR类型的流错误(5.4.2节)。 相应地,如果代理检测到流或HTTP / 2连接有错误,则必须发送设置了RST位的TCP段。

9. 其他HTTP要求/注意事项

本节概述了HTTP协议的属性,这些属性可提高互操作性,减少已知安全漏洞的暴露或减少实现变化的可能性。

9.1. 连接管理

HTTP / 2连接是持久的。 为了获得最佳性能,期望客户端在确定没有必要与服务器进行进一步通信之前(例如,当用户离开特定网页时)或直到服务器关闭连接之前,不会关闭连接。

客户端不应打开与给定主机和端口对的多个HTTP / 2连接,该主机是从URI,选定的替代服务[ALT-SVC]或配置的代理派生的。

客户端可以创建其他连接作为替换,以替换即将用尽可用流标识符空间(第5.1.1节)的连接,刷新TLS连接的密钥资料,或替换遇到错误的连接(第5.4.1节)。

客户端可以使用不同的服务器名称指示[TLS-EXT]值或提供不同的TLS客户端证书打开到同一IP地址和TCP端口的多个连接,但应避免使用相同的配置创建多个连接。

鼓励服务器尽可能长时间地保持打开的连接,但在必要时允许服务器终止空闲连接。 当任一端点选择关闭传输层TCP连接时,终止端点应首先发送GOAWAY(Section 6.8)帧,以便两个端点都能可靠地确定先前发送的帧是否已被处理并正常完成或终止任何剩余的必要任务。

9.1.1. 连接重用

直接或通过使用CONNECT方法(第8.3节)创建的隧道与原始服务器建立的连接,可以重用于具有多个不同URI权限组件的请求。 只要原始服务器具有权威性,就可以重用连接(10.1节)。 对于不带TLS的TCP连接,这取决于已解析为相同IP地址的主机。

对于“ https”资源,连接重用还取决于在URI中具有对主机有效的证书。 当为URI中的主机建立新的TLS连接时,服务器提供的证书必须满足客户端执行的所有检查。

原始服务器可能会提供带有多个“ subjectAltName”属性或带有通配符的名称的证书,其中一个对URI中的授权有效。 例如,“ subjectAltName”为“ * .example.com”的证书可能允许对以“ https://a.example.com/”和“ https://”开头的URI的请求使用相同的连接b.example.com/“。

在某些部署中,将连接重用于多个源可能会导致将请求定向到错误的源服务器。 例如,TL​​S终止可能由使用TLS服务器名称指示(SNI)[TLS-EXT]扩展名的中间盒来选择源服务器。 这意味着,即使服务器具有权威性,客户端也有可能将机密信息发送到可能不是请求目标的服务器。

不希望客户端重用连接的服务器可以通过发送421(错误定向的请求)状态码来响应该请求,以表明该请求不具有权威性(请参阅9.1.2节)。

配置为通过HTTP / 2使用代理的客户端将请求通过单个连接定向到该代理。 也就是说,通过代理发送的所有请求都将重新使用与代理的连接。

9.1.2. 421(错误请求)状态代码

状态代码421(错误定向的请求)指示该请求已定向到无法产生响应的服务器。 这可以由未配置为对请求URI中包含的方案和权限的组合产生响应的服务器发送。

从服务器收到421(错误请求)响应的客户端可以通过不同的连接重试该请求(无论请求方法是否是幂等的)。 如果重新使用连接(第9.1.1节)或选择了备用服务[ALT-SVC],则有可能这样做。

此状态代码不得由代理生成。

默认情况下,421响应是可缓存的,除非方法定义或显式缓存控件另有说明(请参阅[t723] 第4.2.2节)。

9.2. TLS功能的使用

对于通过TLS的HTTP / 2,HTTP / 2的实现必须使用TLS版本1.2 [TLS12]或更高版本。 应当遵循[TLSBCP]中的常规TLS使用指南,并带有一些特定于HTTP / 2的附加限制。

TLS实现必须支持TLS的服务器名称指示(SNI)[TLS-EXT]扩展。 协商TLS时,HTTP / 2客户端务必指示目标域名。

协商TLS 1.3或更高版本的HTTP / 2部署仅需要支持和使用SNI扩展; TLS 1.2的部署必须遵守以下各节的要求。 鼓励实施人员提供符合要求的默认值,但应认识到,部署最终负责遵守法规。

9.2.1. TLS 1.2功能

本节介绍了可与HTTP / 2一起使用的TLS 1.2功能集的限制。 由于部署限制,如果不满足这些限制,则可能无法使TLS协商失败。 端点可以立即终止不满足这些TLS要求的HTTP / 2连接,并出现INADEQUATE_SECURITY类型的连接错误(第5.4.1节)。

在TLS 1.2上部署HTTP / 2必须禁用压缩。 TLS压缩可能导致信息泄露,而这些信息否则就不会泄露[RFC3749]。 通用压缩是不必要的,因为HTTP / 2提供了更了解上下文的压缩功能,因此出于性能,安全性或其他原因可能更适合使用。

在TLS 1.2上部署HTTP / 2务必禁用重新协商。 端点必须将TLS重新协商视为PROTOCOL_ERROR类型的连接错误(第5.4.1节)。 请注意,由于基础密码套件可以加密的消息数量受到限制,因此禁用重新协商可能会导致长期连接无法使用。

端点可以使用重新协商为握手中提供的客户证书提供机密性保护,但是任何重新协商必须在发送连接序言之前进行。 如果服务器在建立连接后立即看到重新协商请求,则应该请求客户端证书。

这有效地防止响应于对特定受保护资源的请求而使用重新协商。 将来的规范可能会提供一种支持此用例的方法。 或者,服务器可能使用HTTP_1_1_REQUIRED类型的错误(第5.4节)来请求客户端使用支持重新协商的协议。

对于使用临时有限域Diffie-Hellman(DHE)[TLS12]的密码套件,实现必须支持至少2048位的临时密钥交换大小;对于使用临时椭圆曲线Diffie-Hellman的密码套件,实现必须支持至少2048位的临时密钥交换大小。 (ECDHE)[RFC4492]。 客户端必须接受最大4096位的DHE大小。 端点可以将小于下限的密钥大小协商视为INADEQUATE_SECURITY类型的连接错误(第5.4.1节)。

9.2.2. TLS 1.2密码套件

通过TLS 1.2部署HTTP / 2不应使用密码套件黑名单(附录A)中列出的任何密码套件。

如果协商了黑名单中的密码套件之一,则端点可以选择生成INADEQUATE_SECURITY类型的连接错误(第5.4.1节)。 选择使用列入黑名单的密码套件的部署可能会引发连接错误,除非已知一组潜在的对等方接受该密码套件。

对于未列入黑名单的密码套件的协商,实现不得产生此错误。 因此,当客户端提供不在黑名单中的密码套件时,他们必须准备将密码套件与HTTP / 2一起使用。

黑名单包括TLS 1.2强制使用的密码套件,这意味着TLS 1.2部署可能具有不相交的允许密码套件集。 为避免此问题导致TLS握手失败,使用TLS 1.2的HTTP / 2部署必须支持TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 [TLS-ECDHE]和P-256椭圆曲线[FIPS186] 。

请注意,客户端可能会宣传对黑名单上的密码套件的支持,以允许连接到不支持HTTP / 2的服务器。 这允许服务器使用HTTP / 2黑名单上的密码套件选择HTTP / 1.1。 但是,如果独立选择应用程序协议和密码套件,则可能导致与黑名单密码套件协商HTTP / 2。

10. 安全注意事项

10.1. 服务器授权

HTTP / 2依靠HTTP / 1.1权限定义来确定服务器在提供给定响应方面是否具有权威性(请参阅[RFC7230],第9.1部分)。 这依赖于“ http” URI方案的本地名称解析和“ https”方案的经过身份验证的服务器身份(请参见[RFC2818],第3部分)。

10.2. 跨协议攻击

在跨协议攻击中,攻击者使客户端以一种协议向了解不同协议的服务器发起事务。 攻击者可能能够使交易在第二协议中显示为有效交易。 结合Web上下文的功能,可以将其与专用网络中受保护不佳的服务器进行交互。

使用HTTP / 2的ALPN标识符完成TLS握手可以被认为是对跨协议攻击的充分保护。 ALPN明确表明服务器愿意继续使用HTTP / 2,从而防止了对其他基于TLS的协议的攻击。

TLS中的加密使攻击者难以控制可用于明文协议跨协议攻击中的数据。

HTTP / 2的明文版本对跨协议攻击的保护最低。 连接序言(第3.5节)包含一个旨在混淆HTTP / 1.1服务器的字符串,但是其他协议没有提供特殊保护。 愿意忽略除客户端连接序言之外还包含Upgrade标头字段的HTTP / 1.1请求的一部分的服务器可能会受到跨协议攻击。

10.3. 中间封装攻击

HTTP / 2标头字段编码允许在HTTP / 1.1使用的Internet消息语法中表达不是有效字段名称的名称。 包含无效头域名称的请求或响应必须被视为格式错误(第8.1.2.6节)。 因此,中介程序无法将包含无效字段名称的HTTP / 2请求或响应转换为HTTP / 1.1消息。

同样,HTTP / 2允许无效的标头字段值。 虽然大多数可以编码的值都不会更改标头字段的解析,但是攻击者可能会利用回车符(CR,ASCII 0xd),换行符(LF,ASCII 0xa)和零字符(NUL,ASCII 0x0)如果将它们逐字翻译。 包含标头字段值中不允许的字符的任何请求或响应都必须被视为格式错误(第8.1.2.6节)。 有效字符由[RFC7230]的3.2节中的“字段内容” ABNF规则定义。

10.4. 推送响应的可缓存性

推送的响应没有来自客户端的明确请求;该请求由服务器在PUSH_PROMISE帧中提供。

根据原始服务器在Cache-Control标头字段中提供的指导,可以推送推送的缓存响应。 但是,如果一台服务器托管多个租户,则可能导致问题。 例如,服务器可能为多个用户提供其URI空间的一小部分。

如果多个租户共享同一台服务器上的空间,则该服务器必须确保租户不能推送他们没有权限的资源的表示形式。 如果不强制执行此操作,则租户可以提供将在缓存之外使用的表示形式,从而覆盖权威性租户提供的实际表示形式。

对于原始服务器没有权威性的推送响应(请参阅第10.1节),不得使用或缓存。

10.5. 拒绝服务注意事项

与HTTP / 1.1连接相比,HTTP / 2连接可能需要更多的资源来进行操作。 头压缩和流控制的使用取决于用于存储大量状态的资源承诺。 这些功能的设置可确保严格限制这些功能的内存承诺。

PUSH_PROMISE帧的数量不受相同方式的限制。 接受服务器推送的客户端应该限制它允许处于“保留(远程)”状态的流的数量。 过多的服务器推送流可被视为类型为ENHANCE_YOUR_CALM的流错误(第5.4.2节)。

处理能力不能像州能力那样有效地受到保护。

SETTINGS帧可能被滥用,导致对等方花费额外的处理时间。 这可以通过无意义地更改SETTINGS参数,设置多个未定义的参数或在同一帧中多次更改相同的设置来完成。 WINDOW_UPDATE或PRIORITY框架可能会被滥用,从而造成不必要的资源浪费。

大量的小帧或空帧可能会被滥用,从而导致对等方花费更多的时间处理帧头。 但是请注意,某些使用是完全合法的,例如在流的末尾发送空的DATA或CONTINUATION帧。

标头压缩还提供了一些浪费处理资源的机会;有关潜在滥用的更多详细信息,请参见[COMPRESSION]的第7节。

不能立即降低SETTINGS参数中的限制,这会使端点暴露于来自对等方的行为,并可能超出新的限制。 特别是,在建立连接后,客户端不知道服务器设置的限制,并且可以在不明显违反协议的情况下超出限制。

所有这些功能-即SETTINGS更改,小帧,标题压缩-具有合法用途。 这些功能仅在不必要或过度使用时才成为负担。

不监视此行为的端点会使自己面临拒绝服务攻击的风险。 实施应跟踪这些功能的使用并设置其使用限制。 端点可以将可疑活动视为ENHANCE_YOUR_CALM类型的连接错误(第5.4.1节)。

10.5.1. 页眉块大小限制

大的标头块(第4.3节)可能导致实现提交大量状态。 对于路由至关重要的标头字段可能会出现在标头块的末尾,这会阻止标头字段流式传输到其最终目的地。 这种排序和其他原因(例如确保高速缓存正确性)意味着端点可能需要缓冲整个标头块。 由于对头块的大小没有硬性限制,因此某些端点可能被迫为头字段提交大量可用内存。

端点可以使用SETTINGS_MAX_HEADER_LIST_SIZE来通知对等端可能适用于标头块大小的限制。 该设置仅是建议性的,因此端点可以选择发送超出此限制的报头块,并有可能将请求或响应视为格式错误。 此设置特定于连接,因此任何请求或响应都可能遇到具有较低未知限制的跃点。 中介可以通过传递不同对等方提供的值来尝试避免此问题,但他们没有义务这样做。

接收到比其愿意处理的头块大的服务器,可以发送HTTP 431(请求头字段太大)状态代码[RFC6585]。 客户端可以丢弃无法处理的响应。 除非关闭连接,否则必须处理头块以确保一致的连接状态。

10.5.2. CONNECT问题

CONNECT方法可用于在代理上创建不成比例的负载,因为与TCP连接的创建和维护相比,流创建相对便宜。 由于传出的TCP连接仍处于TIME_WAIT状态,因此代理可能还会为承载CONNECT请求的流关闭之后的TCP连接保留一些资源。 因此,代理不能仅依靠SETTINGS_MAX_CONCURRENT_STREAMS来限制CONNECT请求消耗的资源。

10.6. 使用压缩

压缩可以使攻击者在与攻击者控制下的数据相同的上下文中对其进行压缩时恢复秘密数据。 HTTP / 2启用头字段的压缩(第4.3节);以下注意事项也适用于HTTP压缩的内容编码([RFC7231],第3.1.2.1节)。

有明显的压缩攻击利用了网络的特征(例如[BREACH])。 攻击者会诱使多个请求包含不同的明文,并观察每个明文中得到的密文的长度,当对秘密的猜测正确时,揭示出较短的长度。

在安全通道上进行通信的实现不得压缩包含机密数据和攻击者控制的数据的内容,除非为每个数据源使用单独的压缩字典。 如果不能可靠地确定数据源,则不得使用压缩。 通用流压缩(例如TLS提供的压缩)不得与HTTP / 2一起使用(请参见第9.2节)。

[COMPRESSION]中描述了有关头字段压缩的其他注意事项。

10.7. 使用填充

HTTP / 2中的填充不打算替代通用填充,例如TLS [TLS12]可能提供的填充。 多余的填充甚至可能适得其反。 正确的应用程序可能取决于对要填充的数据有特定的了解。

为了减轻依赖压缩的攻击,禁用或限制压缩可能比填充更可取。

填充可用于掩盖帧内容的确切大小,并用于缓解HTTP中的特定攻击,例如,压缩内容包括攻击者控制的明文和秘密数据(例如[BREACH ])。

使用填充可能导致的保护作用少于立即显而易见的保护作用。 充其量,填充只会使攻击者更难通过增加攻击者必须观察的帧数来推断长度信息。 错误实现的填充方案很容易被击败。 特别是,具有可预测分布的随机填充提供的保护很少。类似地,将有效载荷填充到固定大小会在有效载荷大小越过固定大小边界时公开信息,如果攻击者可以控制明文,则有可能。

中介应该保留对DATA帧的填充,但是可以对HEADERS和PUSH_PROMISE帧保留填充。 中介机构更改帧填充量的有效原因是为了改进填充提供的保护。

10.8. 隐私注意事项

HTTP / 2的几个特征为观察者提供了一个机会,可以随时间将单个客户端或服务器的操作关联起来。 这些包括设置的值,管理流控制窗口的方式,将优先级分配给流的方式,对刺激的反应时间以及对由设置控制的任何功能的处理。

只要它们在行为上产生可观察到的差异,就可以用作对特定客户端进行指纹识别的基础,如[HTML5]的第1.8节所定义。

HTTP / 2使用单个TCP连接的首选项允许将用户在站点上的活动相关联。 重用不同来源的连接可以跟踪这些来源。

由于PING和SETTINGS帧会请求即时响应,因此端点可以使用它们来度量到其对等方的延迟。 在某些情况下,这可能会对隐私产生影响。

11. IANA注意事项

在[TLS-ALPN]中建立的“应用程序层协议协商(ALPN)协议ID”注册表中输入用于标识HTTP / 2的字符串。

本文档为框架类型,设置和错误代码建立了注册表。 这些新注册表出现在新的“超文本传输​​协议版本2(HTTP / 2)参数”部分中。

本文档注册了HTTP2-Settings标头字段以用于HTTP;它还注册421(错误请求)状态代码。

本文档注册了用于HTTP的“ PRI”方法,以避免与连接序言(第3.5节)冲突。

11.1. HTTP/2 标识字符串的注册

本文档在 [TLS-ALPN] 中建立的“应用层协议协商(ALPN)协议ID”注册表中创建了两个用于标识 HTTP/2 的注册(参见第 3.3 节)。

在 TLS上 使用时,“h2”字符串标识 HTTP/2:

协议:基于 TLS 的 HTTP/2

识别序列:0x68 0x32(“h2”)

规范:本文档

当在明文 TCP 上使用时,“h2c”字符串标识 HTTP/2:

协议:TCP 上的 HTTP/2

识别序列:0x68 0x32 0x63(“h2c”)

规范:本文档

11.2. 框架类型注册表

本文档为HTTP / 2帧类型代码建立注册表。 “ HTTP / 2帧类型”注册表管理一个8位空间。 “ HTTP / 2帧类型”注册表在“ IETF审查”或“ IESG批准”策略[RFC5226]中操作,其值介于0x00和0xef之间,其中0xf0和0xff之间的值被保留实验用途。

此注册表中的新条目需要以下信息:

框架类型:框架类型的名称或标签。

代码:分配给帧类型的8位代码。

规范:对规范的引用,其中包括对帧布局,其语义和帧类型使用的标志的描述,包括基于标志值有条件地存在的帧的任何部分。

下表中的条目由本文档注册。

   +---------------+------+--------------+
   | Frame Type    | Code | Section      |
   +---------------+------+--------------+
   | DATA          | 0x0  | Section 6.1  |
   | HEADERS       | 0x1  | Section 6.2  |
   | PRIORITY      | 0x2  | Section 6.3  |
   | RST_STREAM    | 0x3  | Section 6.4  |
   | SETTINGS      | 0x4  | Section 6.5  |
   | PUSH_PROMISE  | 0x5  | Section 6.6  |
   | PING          | 0x6  | Section 6.7  |
   | GOAWAY        | 0x7  | Section 6.8  |
   | WINDOW_UPDATE | 0x8  | Section 6.9  |
   | CONTINUATION  | 0x9  | Section 6.10 |
   +---------------+------+--------------+
   

11.3. 设置注册表

本文档为HTTP / 2设置建立注册表。 “ HTTP / 2设置”注册表管理一个16位空间。 “ HTTP / 2设置”注册表在“专家审阅”策略[RFC5226]下运行,其值介于0x0000到0xefff之间,且0xf000和0xffff之间的值保留供实验使用。

建议新注册提供以下信息:

名称:设置的符号名称。 指定设置名称是可选的。

代码:分配给设置的16位代码。

初始值:设置的初始值。

规范:对描述该设置用法的规范的可选参考。

下表中的条目由本文档注册。

   +------------------------+------+---------------+---------------+
   | Name                   | Code | Initial Value | Specification |
   +------------------------+------+---------------+---------------+
   | HEADER_TABLE_SIZE      | 0x1  | 4096          | Section 6.5.2 |
   | ENABLE_PUSH            | 0x2  | 1             | Section 6.5.2 |
   | MAX_CONCURRENT_STREAMS | 0x3  | (infinite)    | Section 6.5.2 |
   | INITIAL_WINDOW_SIZE    | 0x4  | 65535         | Section 6.5.2 |
   | MAX_FRAME_SIZE         | 0x5  | 16384         | Section 6.5.2 |
   | MAX_HEADER_LIST_SIZE   | 0x6  | (infinite)    | Section 6.5.2 |
   +------------------------+------+---------------+---------------+
    

11.4. 错误代码注册表

本文档为HTTP / 2错误代码建立了一个注册表。 “ HTTP / 2错误代码”注册表管理一个32位空间。 “ HTTP / 2错误代码”注册表在“专家审阅”策略[RFC5226]下运行。

需要注册错误代码以包含错误代码的描述。 建议专家审阅者检查新注册是否与现有错误代码重复。 鼓励但不强制使用现有注册。

建议新注册提供以下信息:

名称:错误代码的名称。 指定错误代码名称是可选的。

代码:32位错误代码值。

描述:错误代码语义的简短描述,如果未提供详细说明,则更长。

规范:定义错误代码的规范的可选参考。

下表中的条目由本文档注册。

   +---------------------+------+----------------------+---------------+
   | Name                | Code | Description          | Specification |
   +---------------------+------+----------------------+---------------+
   | NO_ERROR            | 0x0  | Graceful shutdown    | Section 7     |
   | PROTOCOL_ERROR      | 0x1  | Protocol error       | Section 7     |
   |                     |      | detected             |               |
   | INTERNAL_ERROR      | 0x2  | Implementation fault | Section 7     |
   | FLOW_CONTROL_ERROR  | 0x3  | Flow-control limits  | Section 7     |
   |                     |      | exceeded             |               |
   | SETTINGS_TIMEOUT    | 0x4  | Settings not         | Section 7     |
   |                     |      | acknowledged         |               |
   | STREAM_CLOSED       | 0x5  | Frame received for   | Section 7     |
   |                     |      | closed stream        |               |
   | FRAME_SIZE_ERROR    | 0x6  | Frame size incorrect | Section 7     |
   | REFUSED_STREAM      | 0x7  | Stream not processed | Section 7     |
   | CANCEL              | 0x8  | Stream cancelled     | Section 7     |
   | COMPRESSION_ERROR   | 0x9  | Compression state    | Section 7     |
   |                     |      | not updated          |               |
   | CONNECT_ERROR       | 0xa  | TCP connection error | Section 7     |
   |                     |      | for CONNECT method   |               |
   | ENHANCE_YOUR_CALM   | 0xb  | Processing capacity  | Section 7     |
   |                     |      | exceeded             |               |
   | INADEQUATE_SECURITY | 0xc  | Negotiated TLS       | Section 7     |
   |                     |      | parameters not       |               |
   |                     |      | acceptable           |               |
   | HTTP_1_1_REQUIRED   | 0xd  | Use HTTP/1.1 for the | Section 7     |
   |                     |      | request              |               |
   +---------------------+------+----------------------+---------------+
   

11.5. HTTP2-设置标题字段注册

本节将HTTP2-Settings头字段注册在“永久消息头字段名称”注册表[BCP90]中。

标头字段名称:HTTP2-Settings

适用协议:http

状态:标准

作者/变更控制者:IETF

规范文档:本文档的第3.2.1节

相关信息:此标头字段仅由HTTP / 2客户端用于基于升级的协商。

11.6. PRI方法注册

本节在“ HTTP方法注册表”([RFC7231],第8.1节)中注册“ PRI”方法。

方法名称:PRI

安全:是

幂等

规范文档:本文档的3.5节

相关信息:实际客户端永远不会使用此方法。 当HTTP / 1.1服务器或中介尝试解析HTTP / 2连接前言时,似乎会使用此方法。

11.7. 421(错误定向的请求)HTTP状态代码

本文档在“ HTTP状态代码”注册表中注册了421(错误请求)HTTP状态代码([RFC7231],第8.2部分)。

状态码:421

简短说明:错误的请求

规范:本文档的第9.1.2节

11.8. h2c升级令牌

本文档在“ HTTP升级令牌”注册表中注册了“ h2c”升级令牌([RFC7230],第8.6节)。

值:h2c

说明:超文本传输​​协议版本2(HTTP / 2)

预期版本令牌:无

参考:本文档的3.2节

12. 参考文献

12.1. 规范性引用

   
   [COMPRESSION] Peon, R. and H. Ruellan, "HPACK: Header Compression for
                 HTTP/2", RFC 7541, DOI 10.17487/RFC7541, May 2015,
                 <http://www.rfc-editor.org/info/rfc7541>.

   [COOKIE]      Barth, A., "HTTP State Management Mechanism", RFC 6265,
                 DOI 10.17487/RFC6265, April 2011,
                 <http://www.rfc-editor.org/info/rfc6265>.

   [FIPS186]     NIST, "Digital Signature Standard (DSS)", FIPS PUB
                 186-4, July 2013,
                 <http://dx.doi.org/10.6028/NIST.FIPS.186-4>.

   [RFC2119]     Bradner, S., "Key words for use in RFCs to Indicate
                 Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/
                 RFC2119, March 1997,
                 <http://www.rfc-editor.org/info/rfc2119>.

   [RFC2818]     Rescorla, E., "HTTP Over TLS", RFC 2818, DOI 10.17487/
                 RFC2818, May 2000,
                 <http://www.rfc-editor.org/info/rfc2818>.

   [RFC3986]     Berners-Lee, T., Fielding, R., and L. Masinter,
                 "Uniform Resource Identifier (URI): Generic Syntax",
                 STD 66, RFC 3986, DOI 10.17487/RFC3986, January 2005,
                 <http://www.rfc-editor.org/info/rfc3986>.

   [RFC4648]     Josefsson, S., "The Base16, Base32, and Base64 Data
                 Encodings", RFC 4648, DOI 10.17487/RFC4648, October
                 2006, <http://www.rfc-editor.org/info/rfc4648>.

   [RFC5226]     Narten, T. and H. Alvestrand, "Guidelines for Writing
                 an IANA Considerations Section in RFCs", BCP 26,
                 RFC 5226, DOI 10.17487/RFC5226, May 2008,
                 <http://www.rfc-editor.org/info/rfc5226>.

   [RFC5234]     Crocker, D., Ed. and P. Overell, "Augmented BNF for
                 Syntax Specifications: ABNF", STD 68, RFC 5234,
                 DOI 10.17487/ RFC5234, January 2008,
                 <http://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, DOI 10.17487/RFC7230, June 2014,
                 <http://www.rfc-editor.org/info/rfc7230>.

   [RFC7231]     Fielding, R., Ed. and J. Reschke, Ed., "Hypertext
                 Transfer Protocol (HTTP/1.1): Semantics and Content",
                 RFC 7231, DOI 10.17487/RFC7231, June 2014,
                 <http://www.rfc-editor.org/info/rfc7231>.

   [RFC7232]     Fielding, R., Ed. and J. Reschke, Ed., "Hypertext
                 Transfer Protocol (HTTP/1.1): Conditional Requests",
                 RFC 7232, DOI 10.17487/RFC7232, June 2014,
                 <http://www.rfc-editor.org/info/rfc7232>.

   [RFC7233]     Fielding, R., Ed., Lafon, Y., Ed., and J. Reschke, Ed.,
                 "Hypertext Transfer Protocol (HTTP/1.1): Range
                 Requests", RFC 7233, DOI 10.17487/RFC7233, June 2014,
                 <http://www.rfc-editor.org/info/rfc7233>.

   [RFC7234]     Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke,
                 Ed., "Hypertext Transfer Protocol (HTTP/1.1): Caching",
                 RFC 7234, DOI 10.17487/RFC7234, June 2014,
                 <http://www.rfc-editor.org/info/rfc7234>.

   [RFC7235]     Fielding, R., Ed. and J. Reschke, Ed., "Hypertext
                 Transfer Protocol (HTTP/1.1): Authentication",
                 RFC 7235, DOI 10.17487/RFC7235, June 2014,
                 <http://www.rfc-editor.org/info/rfc7235>.

   [TCP]         Postel, J., "Transmission Control Protocol", STD 7, RFC
                 793, DOI 10.17487/RFC0793, September 1981,
                 <http://www.rfc-editor.org/info/rfc793>.

   [TLS-ALPN]    Friedl, S., Popov, A., Langley, A., and E. Stephan,
                 "Transport Layer Security (TLS) Application-Layer
                 Protocol Negotiation Extension", RFC 7301,
                 DOI 10.17487/RFC7301, July 2014,
                 <http://www.rfc-editor.org/info/rfc7301>.

   [TLS-ECDHE]   Rescorla, E., "TLS Elliptic Curve Cipher Suites with
                 SHA-256/384 and AES Galois Counter Mode (GCM)",
                 RFC 5289, DOI 10.17487/RFC5289, August 2008,
                 <http://www.rfc-editor.org/info/rfc5289>.

   [TLS-EXT]     Eastlake 3rd, D., "Transport Layer Security (TLS)
                 Extensions: Extension Definitions", RFC 6066,
                 DOI 10.17487/RFC6066, January 2011,
                 <http://www.rfc-editor.org/info/rfc6066>.

   [TLS12]       Dierks, T. and E. Rescorla, "The Transport Layer
                 Security (TLS) Protocol Version 1.2", RFC 5246,
                 DOI 10.17487/ RFC5246, August 2008,
                 <http://www.rfc-editor.org/info/rfc5246>.

    

12.2. 信息参考

    
   [ALT-SVC]     Nottingham, M., McManus, P., and J. Reschke, "HTTP
                 Alternative Services", Work in Progress, draft-ietf-
                 httpbis-alt-svc-06, February 2015.

   [BCP90]       Klyne, G., Nottingham, M., and J. Mogul, "Registration
                 Procedures for Message Header Fields", BCP 90,
                 RFC 3864, September 2004,
                 <http://www.rfc-editor.org/info/bcp90>.

   [BREACH]      Gluck, Y., Harris, N., and A. Prado, "BREACH: Reviving
                 the CRIME Attack", July 2013,
                 <http://breachattack.com/resources/
                 BREACH%20-%20SSL,%20gone%20in%2030%20seconds.pdf>.

   [HTML5]       Hickson, I., Berjon, R., Faulkner, S., Leithead, T.,
                 Doyle Navara, E., O'Connor, E., and S. Pfeiffer,
                 "HTML5", W3C Recommendation REC-html5-20141028, October
                 2014, <http://www.w3.org/TR/2014/REC-html5-20141028/>.

   [RFC3749]     Hollenbeck, S., "Transport Layer Security Protocol
                 Compression Methods", RFC 3749, DOI 10.17487/RFC3749,
                 May 2004, <http://www.rfc-editor.org/info/rfc3749>.

   [RFC4492]     Blake-Wilson, S., Bolyard, N., Gupta, V., Hawk, C., and
                 B.  Moeller, "Elliptic Curve Cryptography (ECC) Cipher
                 Suites for Transport Layer Security (TLS)", RFC 4492,
                 DOI 10.17487/RFC4492, May 2006,
                 <http://www.rfc-editor.org/info/rfc4492>.

   [RFC6585]     Nottingham, M. and R. Fielding, "Additional HTTP Status
                 Codes", RFC 6585, DOI 10.17487/RFC6585, April 2012,
                 <http://www.rfc-editor.org/info/rfc6585>.

   [RFC7323]     Borman, D., Braden, B., Jacobson, V., and R.
                 Scheffenegger, Ed., "TCP Extensions for High
                 Performance", RFC 7323, DOI 10.17487/RFC7323, September
                 2014, <http://www.rfc-editor.org/info/rfc7323>.

   [TALKING]     Huang, L., Chen, E., Barth, A., Rescorla, E., and C.
                 Jackson, "Talking to Yourself for Fun and Profit",
                 2011, <http://w2spconf.com/2011/papers/websocket.pdf>.

   [TLSBCP]      Sheffer, Y., Holz, R., and P. Saint-Andre,
                 "Recommendations for Secure Use of Transport Layer
                 Security (TLS) and Datagram Transport Layer Security
                 (DTLS)", BCP 195, RFC 7525, DOI 10.17487/RFC7525, May
                 2015, <http://www.rfc-editor.org/info/rfc7525>.

    

附录 A. TLS 1.2 Cipher Suite 黑名单

   An HTTP/2 implementation MAY treat the negotiation of any of the
   following cipher suites with TLS 1.2 as a connection error
   (Section 5.4.1) of type INADEQUATE_SECURITY:

   o  TLS_NULL_WITH_NULL_NULL

   o  TLS_RSA_WITH_NULL_MD5

   o  TLS_RSA_WITH_NULL_SHA

   o  TLS_RSA_EXPORT_WITH_RC4_40_MD5

   o  TLS_RSA_WITH_RC4_128_MD5

   o  TLS_RSA_WITH_RC4_128_SHA

   o  TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5

   o  TLS_RSA_WITH_IDEA_CBC_SHA

   o  TLS_RSA_EXPORT_WITH_DES40_CBC_SHA

   o  TLS_RSA_WITH_DES_CBC_SHA

   o  TLS_RSA_WITH_3DES_EDE_CBC_SHA

   o  TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA

   o  TLS_DH_DSS_WITH_DES_CBC_SHA

   o  TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA

   o  TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA

   o  TLS_DH_RSA_WITH_DES_CBC_SHA

   o  TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA

   o  TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA

   o  TLS_DHE_DSS_WITH_DES_CBC_SHA

   o  TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA

   o  TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA

   o  TLS_DHE_RSA_WITH_DES_CBC_SHA

   o  TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA

   o  TLS_DH_anon_EXPORT_WITH_RC4_40_MD5

   o  TLS_DH_anon_WITH_RC4_128_MD5

   o  TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA

   o  TLS_DH_anon_WITH_DES_CBC_SHA

   o  TLS_DH_anon_WITH_3DES_EDE_CBC_SHA

   o  TLS_KRB5_WITH_DES_CBC_SHA

   o  TLS_KRB5_WITH_3DES_EDE_CBC_SHA

   o  TLS_KRB5_WITH_RC4_128_SHA

   o  TLS_KRB5_WITH_IDEA_CBC_SHA

   o  TLS_KRB5_WITH_DES_CBC_MD5

   o  TLS_KRB5_WITH_3DES_EDE_CBC_MD5

   o  TLS_KRB5_WITH_RC4_128_MD5

   o  TLS_KRB5_WITH_IDEA_CBC_MD5

   o  TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA

   o  TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA

   o  TLS_KRB5_EXPORT_WITH_RC4_40_SHA

   o  TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5

   o  TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5

   o  TLS_KRB5_EXPORT_WITH_RC4_40_MD5

   o  TLS_PSK_WITH_NULL_SHA

   o  TLS_DHE_PSK_WITH_NULL_SHA

   o  TLS_RSA_PSK_WITH_NULL_SHA

   o  TLS_RSA_WITH_AES_128_CBC_SHA

   o  TLS_DH_DSS_WITH_AES_128_CBC_SHA

   o  TLS_DH_RSA_WITH_AES_128_CBC_SHA

   o  TLS_DHE_DSS_WITH_AES_128_CBC_SHA

   o  TLS_DHE_RSA_WITH_AES_128_CBC_SHA

   o  TLS_DH_anon_WITH_AES_128_CBC_SHA

   o  TLS_RSA_WITH_AES_256_CBC_SHA

   o  TLS_DH_DSS_WITH_AES_256_CBC_SHA

   o  TLS_DH_RSA_WITH_AES_256_CBC_SHA

   o  TLS_DHE_DSS_WITH_AES_256_CBC_SHA

   o  TLS_DHE_RSA_WITH_AES_256_CBC_SHA

   o  TLS_DH_anon_WITH_AES_256_CBC_SHA

   o  TLS_RSA_WITH_NULL_SHA256

   o  TLS_RSA_WITH_AES_128_CBC_SHA256

   o  TLS_RSA_WITH_AES_256_CBC_SHA256

   o  TLS_DH_DSS_WITH_AES_128_CBC_SHA256

   o  TLS_DH_RSA_WITH_AES_128_CBC_SHA256

   o  TLS_DHE_DSS_WITH_AES_128_CBC_SHA256

   o  TLS_RSA_WITH_CAMELLIA_128_CBC_SHA

   o  TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA

   o  TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA

   o  TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA

   o  TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA

   o  TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA

   o  TLS_DHE_RSA_WITH_AES_128_CBC_SHA256

   o  TLS_DH_DSS_WITH_AES_256_CBC_SHA256

   o  TLS_DH_RSA_WITH_AES_256_CBC_SHA256

   o  TLS_DHE_DSS_WITH_AES_256_CBC_SHA256

   o  TLS_DHE_RSA_WITH_AES_256_CBC_SHA256

   o  TLS_DH_anon_WITH_AES_128_CBC_SHA256

   o  TLS_DH_anon_WITH_AES_256_CBC_SHA256

   o  TLS_RSA_WITH_CAMELLIA_256_CBC_SHA

   o  TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA

   o  TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA

   o  TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA

   o  TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA

   o  TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA

   o  TLS_PSK_WITH_RC4_128_SHA

   o  TLS_PSK_WITH_3DES_EDE_CBC_SHA

   o  TLS_PSK_WITH_AES_128_CBC_SHA

   o  TLS_PSK_WITH_AES_256_CBC_SHA

   o  TLS_DHE_PSK_WITH_RC4_128_SHA

   o  TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA

   o  TLS_DHE_PSK_WITH_AES_128_CBC_SHA

   o  TLS_DHE_PSK_WITH_AES_256_CBC_SHA

   o  TLS_RSA_PSK_WITH_RC4_128_SHA

   o  TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA

   o  TLS_RSA_PSK_WITH_AES_128_CBC_SHA

   o  TLS_RSA_PSK_WITH_AES_256_CBC_SHA

   o  TLS_RSA_WITH_SEED_CBC_SHA

   o  TLS_DH_DSS_WITH_SEED_CBC_SHA

   o  TLS_DH_RSA_WITH_SEED_CBC_SHA

   o  TLS_DHE_DSS_WITH_SEED_CBC_SHA

   o  TLS_DHE_RSA_WITH_SEED_CBC_SHA

   o  TLS_DH_anon_WITH_SEED_CBC_SHA

   o  TLS_RSA_WITH_AES_128_GCM_SHA256

   o  TLS_RSA_WITH_AES_256_GCM_SHA384

   o  TLS_DH_RSA_WITH_AES_128_GCM_SHA256

   o  TLS_DH_RSA_WITH_AES_256_GCM_SHA384

   o  TLS_DH_DSS_WITH_AES_128_GCM_SHA256

   o  TLS_DH_DSS_WITH_AES_256_GCM_SHA384

   o  TLS_DH_anon_WITH_AES_128_GCM_SHA256

   o  TLS_DH_anon_WITH_AES_256_GCM_SHA384

   o  TLS_PSK_WITH_AES_128_GCM_SHA256

   o  TLS_PSK_WITH_AES_256_GCM_SHA384

   o  TLS_RSA_PSK_WITH_AES_128_GCM_SHA256

   o  TLS_RSA_PSK_WITH_AES_256_GCM_SHA384

   o  TLS_PSK_WITH_AES_128_CBC_SHA256

   o  TLS_PSK_WITH_AES_256_CBC_SHA384

   o  TLS_PSK_WITH_NULL_SHA256

   o  TLS_PSK_WITH_NULL_SHA384

   o  TLS_DHE_PSK_WITH_AES_128_CBC_SHA256

   o  TLS_DHE_PSK_WITH_AES_256_CBC_SHA384

   o  TLS_DHE_PSK_WITH_NULL_SHA256

   o  TLS_DHE_PSK_WITH_NULL_SHA384

   o  TLS_RSA_PSK_WITH_AES_128_CBC_SHA256

   o  TLS_RSA_PSK_WITH_AES_256_CBC_SHA384

   o  TLS_RSA_PSK_WITH_NULL_SHA256

   o  TLS_RSA_PSK_WITH_NULL_SHA384

   o  TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256

   o  TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256

   o  TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256

   o  TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256

   o  TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256

   o  TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256

   o  TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256

   o  TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256

   o  TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256

   o  TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256

   o  TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256

   o  TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256

   o  TLS_EMPTY_RENEGOTIATION_INFO_SCSV

   o  TLS_ECDH_ECDSA_WITH_NULL_SHA

   o  TLS_ECDH_ECDSA_WITH_RC4_128_SHA

   o  TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA

   o  TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA

   o  TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA

   o  TLS_ECDHE_ECDSA_WITH_NULL_SHA

   o  TLS_ECDHE_ECDSA_WITH_RC4_128_SHA

   o  TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA

   o  TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA

   o  TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA

   o  TLS_ECDH_RSA_WITH_NULL_SHA

   o  TLS_ECDH_RSA_WITH_RC4_128_SHA

   o  TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA

   o  TLS_ECDH_RSA_WITH_AES_128_CBC_SHA

   o  TLS_ECDH_RSA_WITH_AES_256_CBC_SHA

   o  TLS_ECDHE_RSA_WITH_NULL_SHA

   o  TLS_ECDHE_RSA_WITH_RC4_128_SHA

   o  TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA

   o  TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA

   o  TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA

   o  TLS_ECDH_anon_WITH_NULL_SHA

   o  TLS_ECDH_anon_WITH_RC4_128_SHA

   o  TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA

   o  TLS_ECDH_anon_WITH_AES_128_CBC_SHA

   o  TLS_ECDH_anon_WITH_AES_256_CBC_SHA

   o  TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA

   o  TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA

   o  TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA

   o  TLS_SRP_SHA_WITH_AES_128_CBC_SHA

   o  TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA

   o  TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA

   o  TLS_SRP_SHA_WITH_AES_256_CBC_SHA

   o  TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA

   o  TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA

   o  TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256

   o  TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384

   o  TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256

   o  TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384

   o  TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256

   o  TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384

   o  TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256

   o  TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384

   o  TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256

   o  TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384

   o  TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256

   o  TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384

   o  TLS_ECDHE_PSK_WITH_RC4_128_SHA

   o  TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA

   o  TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA

   o  TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA

   o  TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256

   o  TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384

   o  TLS_ECDHE_PSK_WITH_NULL_SHA

   o  TLS_ECDHE_PSK_WITH_NULL_SHA256

   o  TLS_ECDHE_PSK_WITH_NULL_SHA384

   o  TLS_RSA_WITH_ARIA_128_CBC_SHA256

   o  TLS_RSA_WITH_ARIA_256_CBC_SHA384

   o  TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256

   o  TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384

   o  TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256

   o  TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384

   o  TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256

   o  TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384

   o  TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256

   o  TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384

   o  TLS_DH_anon_WITH_ARIA_128_CBC_SHA256

   o  TLS_DH_anon_WITH_ARIA_256_CBC_SHA384

   o  TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256

   o  TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384

   o  TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256

   o  TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384

   o  TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256

   o  TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384

   o  TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256

   o  TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384

   o  TLS_RSA_WITH_ARIA_128_GCM_SHA256

   o  TLS_RSA_WITH_ARIA_256_GCM_SHA384

   o  TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256

   o  TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384

   o  TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256

   o  TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384

   o  TLS_DH_anon_WITH_ARIA_128_GCM_SHA256

   o  TLS_DH_anon_WITH_ARIA_256_GCM_SHA384

   o  TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256

   o  TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384

   o  TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256

   o  TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384

   o  TLS_PSK_WITH_ARIA_128_CBC_SHA256

   o  TLS_PSK_WITH_ARIA_256_CBC_SHA384

   o  TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256

   o  TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384

   o  TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256

   o  TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384

   o  TLS_PSK_WITH_ARIA_128_GCM_SHA256

   o  TLS_PSK_WITH_ARIA_256_GCM_SHA384

   o  TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256

   o  TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384

   o  TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256

   o  TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384

   o  TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256

   o  TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384

   o  TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256

   o  TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384

   o  TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256

   o  TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384

   o  TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256

   o  TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384

   o  TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256

   o  TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384

   o  TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256

   o  TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384

   o  TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256

   o  TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384

   o  TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256

   o  TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384

   o  TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256

   o  TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384

   o  TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256

   o  TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384

   o  TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256

   o  TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384

   o  TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256

   o  TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384

   o  TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256

   o  TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384

   o  TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256

   o  TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384

   o  TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256

   o  TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384

   o  TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256

   o  TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384

   o  TLS_RSA_WITH_AES_128_CCM

   o  TLS_RSA_WITH_AES_256_CCM

   o  TLS_RSA_WITH_AES_128_CCM_8

   o  TLS_RSA_WITH_AES_256_CCM_8

   o  TLS_PSK_WITH_AES_128_CCM

   o  TLS_PSK_WITH_AES_256_CCM

   o  TLS_PSK_WITH_AES_128_CCM_8

   o  TLS_PSK_WITH_AES_256_CCM_8

      Note: This list was assembled from the set of registered TLS
      cipher suites at the time of writing.  This list includes those
      cipher suites that do not offer an ephemeral key exchange and
      those that are based on the TLS null, stream, or block cipher type
      (as defined in Section 6.2.3 of [TLS12]).  Additional cipher
      suites with these properties could be defined; these would not be
      explicitly prohibited.

   This document includes substantial input from the following
   individuals:

   o  Adam Langley, Wan-Teh Chang, Jim Morrison, Mark Nottingham, Alyssa
      Wilk, Costin Manolache, William Chan, Vitaliy Lvin, Joe Chan, Adam
      Barth, Ryan Hamilton, Gavin Peters, Kent Alstad, Kevin Lindsay,
      Paul Amer, Fan Yang, and Jonathan Leighton (SPDY contributors).

   o  Gabriel Montenegro and Willy Tarreau (Upgrade mechanism).

   o  William Chan, Salvatore Loreto, Osama Mazahir, Gabriel Montenegro,
      Jitu Padhye, Roberto Peon, and Rob Trace (Flow control).

   o  Mike Bishop (Extensibility).

   o  Mark Nottingham, Julian Reschke, James Snell, Jeff Pinner, Mike
      Bishop, and Herve Ruellan (Substantial editorial contributions).

   o  Kari Hurtta, Tatsuhiro Tsujikawa, Greg Wilkins, Poul-Henning Kamp,
      and Jonathan Thackray.

   o  Alexey Melnikov, who was an editor of this document in 2013.

   A substantial proportion of Martin's contribution was supported by
   Microsoft during his employment there.

   The Japanese HTTP/2 community provided invaluable contributions,
   including a number of implementations as well as numerous technical
   and editorial contributions.


Authors' Addresses

   Mike Belshe
   BitGo

   EMail: mike@belshe.com


   Roberto Peon
   Google, Inc

   EMail: fenix@google.com


   Martin Thomson (editor)
   Mozilla
   331 E Evelyn Street
   Mountain View, CA  94041
   United States

   EMail: martin.thomson@gmail.com