为什么 Huffman 编码在 HTTP/2 HPACK 中是可选的?

Why Is Huffman Encoding Optional in HTTP/2 HPACK?

我想确保我理解正确: 这是来自section 5.2 of RFC7451

   Header field names and header field values can be represented as
   string literals.  A string literal is encoded as a sequence of
   octets, either by directly encoding the string literal's octets or by
   using a Huffman code (see [HUFFMAN]).

     0   1   2   3   4   5   6   7
   +---+---+---+---+---+---+---+---+
   | H |    String Length (7+)     |
   +---+---------------------------+
   |  String Data (Length octets)  |
   +-------------------------------+

这意味着我可以发送 Header 字符串文字,其中 H 为 1,带有霍夫曼编码字符串;或 H 为 0 且原始字符串八位字节;并且现有的 HTTP/2 server/implementation 应该正确解析它们,对吗?

HTTPHeaders基本上都是由ASCII码组成的。 ASCII 使用固定长度的代码,其中每个字符的长度为 8 位(实际上只有 7 位,因为 HTTP Headers 仅使用原始 ASCII 字符集中的前 127 个代码,但第 8 位设置为 0)。

哈夫曼编码使用可变长度编码。较常用的字符具有小于 8 位的较短代码,而不太常用的字符具有超过 8 位的代码。大多数文本的理论是由更频繁使用的代码组成的,因此在大多数情况下长度应该比 ASCII 短。尤其如此,因为 ASCII 在仅使用只需要 7 位的基本字符时会“浪费”一点,但将其保存在 space.

的 8 位中

因此如果使用哈夫曼编码,将会有一些文本实际上比 ASCII 更长。

显示了 HPACK 中使用的霍夫曼编码 table here,作为示例,您可以看到 < 被编码为 111111111111100,即 15 位。因此,霍夫曼编码字符串 <<<< 在 ASCII 中需要 4 个八位字节,但在霍夫曼编码中需要 60 位或 8 个八位字节。

因此 HPACK 允许您在这种情况下使用 ASCII,因为这样效率更高。

也许这有点过于复杂,我们应该接受在这些罕见的边缘情况下效率稍低的编码——有人说 IETF 痴迷于节省比特——但这就是它存在的原因。

请注意,接收方无法控制另一方使用的内容,因此每个 HTTP/2 实现都需要了解霍夫曼编码。所以它不是可选的,因为你可以在没有它的情况下进行 HTTP/2 实现,但是将它用于单个 header 名称或值是可选的。

顺便说一句,如果有兴趣比规范给出的更详细地了解 HPACK,那么我会在我的书的第 8 章中介绍它(包括这个问题的答案!):https://www.manning.com/books/http2-in-action.