RFC 7541: HPACK: Header Compression for HTTP/2
总结此页面
全文总结
本文档为《HPACK: Header Compression for HTTP/2》,由 R. Peon 撰写,属于互联网标准轨道文档。该规范定义了 HPACK,一种用于高效表示 HTTP 头字段的压缩格式,用于 HTTP/2。文档详细介绍了 HPACK 的各个方面,包括压缩过程概述、头块解码、动态表管理、基本类型表示、二进制格式和安全考虑等内容。
重要亮点
HPACK 的定义和目的:HPACK 是一种用于 HTTP/2 的头字段压缩格式,旨在消除冗余头字段、限制已知安全攻击的脆弱性,并在受限环境中有有限的内存需求。它的格式简单且不灵活,以减少因实现错误导致的互操作性或安全问题的风险。
压缩过程概述:HPACK 不描述特定的编码器算法,而是精确定义了解码器的操作方式。它使用两个表(静态表和动态表)将头字段映射到索引值,编码时可以根据头字段的顺序和安全性考虑选择不同的表示方式,包括索引表示和三种不同的字面量表示。
头块解码:解码器按顺序处理头块以重建原始头列表,处理过程中遵循特定规则,确保成功解码并产生头列表。一旦头字段被解码并添加到头列表中,就不能被删除。
动态表管理:为了限制解码器的内存需求,动态表的大小受到严格限制。可以通过计算表大小、设置最大表大小、在表大小变化时进行条目驱逐以及在添加新条目时进行条目驱逐等方式来管理动态表。
基本类型表示:HPACK 编码使用两种基本类型,即无符号可变长度整数和字节字符串。整数表示可以在字节的任何位置开始,为了优化处理,总是在字节的末尾结束。字符串字面量可以直接编码或使用霍夫曼编码。
二进制格式:详细描述了不同头字段表示和动态表大小更新指令的二进制格式,包括索引头字段表示、三种字面量头字段表示(带增量索引、不带索引和永不索引)。
给一个编码样例并解释
以下是一个使用 HPACK 进行编码的样例,并对其进行解释。
样例:编码请求头字段
假设我们要编码以下 HTTP/2 请求头字段:
:method: GET
:scheme: http
:path: /
:authority: www.example.com
编码过程解释
:method: GET
因为:method: GET是静态表中的常见头字段,其索引为 2(参考文档中的静态表定义)。所以在 HPACK 中,它将被编码为一个索引头字段表示。
二进制格式为:82
解释:按照索引头字段表示的格式(文档中 6.1 节),它以1开头,后面跟着索引值。这里索引值为 2,用 7 位前缀表示就是0000010,所以整体就是10000010,十六进制为82。
:scheme: http
同样是静态表中的常见头字段,索引为 6。
二进制格式为:86
解释:以1开头,索引值 6 用 7 位前缀表示为0000110,即10000110,十六进制为86。
:path: /
也是静态表中的常见头字段,索引为 4。
二进制格式为:84
解释:以1开头,索引值 4 用 7 位前缀表示为0000100,即10000100,十六进制为84。
:authority: www.example.com
对于:authority这个头字段,由于它可能是首次出现或者在动态表中没有对应的索引,将使用字面量头字段表示且添加到动态表(增量索引)。
假设www.example.com字符串长度编码后为 15(这里省略具体字符串长度编码过程,可参考文档中 5.1 节和 5.2 节关于整数和字符串字面量编码)。
二进制格式为:410f77772e6578616d706c652e636f6d
解释:
按照字面量头字段带增量索引的格式(文档中 6.2.1 节),它以01开头。如果头字段名称匹配静态表或动态表中的条目,可以用索引表示,这里:authority可以用索引 1 表示(在一些特定的索引空间规则下),用 6 位前缀表示为000001。
然后是值长度,这里假设为 15,用 7 位前缀表示可能是0001111(实际编码可能因整数编码规则有细微差异)。
最后是值本身的字节序列,即www.example.com的编码。
整体编码结果
将上述编码结果组合起来,对于这个请求头字段的 HPACK 编码就是:828684410f77772e6578616d706c652e636f6d。这个编码结果将在 HTTP/2 通信中用于传输头字段信息,接收方可以根据 HPACK 的解码规则进行解码,还原出原始的头字段。
接收方和发送方如何约定 HPACK 的解码规则
接收方和发送方通过以下方式约定 HPACK 的解码规则:
标准规范约定
遵循 RFC 标准:HPACK 的规范在 RFC 7541 中详细定义。发送方和接收方都需要遵循这个标准文档中规定的各种规则和算法。例如,对于头字段的表示方式(索引表示、字面量表示等)、动态表的管理规则、整数和字符串的编码规则等都有明确的定义。双方都按照这些标准规范来实现编码和解码逻辑,以确保能够正确地处理和理解对方发送的数据。
协议协商确定参数
SETTINGS_HEADER_TABLE_SIZE 参数:在 HTTP/2 协议中,通过SETTINGS_HEADER_TABLE_SIZE这个设置参数来协商动态表的大小。发送方和接收方在建立连接时,会通过协议的相关机制交换这个参数的值。这个参数决定了动态表在接收方可以使用的最大内存空间,发送方在编码过程中需要考虑这个限制,不能超过接收方所允许的动态表大小。接收方则根据这个参数来管理动态表的内存使用,当动态表大小达到或接近这个限制时,可能会进行一些清理或驱逐操作。
其他可能的参数:除了动态表大小参数外,虽然 HPACK 本身相对固定,但在 HTTP/2 协议的框架下,可能还会有一些其他相关的参数或配置信息影响着 HPACK 的使用。例如,协议版本相关的一些特性或设置可能会对 HPACK 的某些行为产生影响,双方需要确保对这些协议相关的参数和特性有一致的理解和配置。
初始状态的一致性
静态表的一致性:HPACK 使用了一个预定义的静态表,其中包含了常见的头字段及其索引。发送方和接收方都使用相同的静态表定义,这是确保正确解码的基础。例如,双方都知道:method: GET在静态表中的索引是 2,这样当发送方发送一个索引值为 2 的头字段表示时,接收方能够正确地识别它代表的是:method: GET这个头字段。
动态表的初始状态:动态表在开始时是为空的,这是双方都默认的初始状态。随着头块的解码,动态表会逐渐被填充。发送方和接收方都从这个相同的初始状态开始,并且在处理每个头块时,根据规范更新动态表的状态。例如,当发送方发送一个带有增量索引的字面量头字段时,接收方会按照规则将其添加到动态表中,并在后续的解码过程中可能会使用到这个新添加的条目。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。