【发布时间】:2021-12-02 11:13:23
【问题描述】:
来自 RFC7540:
虽然 HTTP/1.x 使用消息起始行(参见 [RFC7230],第 3.1 节)来传达目标 URI、请求的方法和响应的状态代码,但 HTTP/2 使用特殊的伪- 以 ':' 字符 (ASCII 0x3a) 开头的标题字段用于此目的。
那么为什么 HTTP/2 使用伪标头字段? HTTP/1.x 中的消息起始行有什么问题吗?
【问题讨论】:
来自 RFC7540:
虽然 HTTP/1.x 使用消息起始行(参见 [RFC7230],第 3.1 节)来传达目标 URI、请求的方法和响应的状态代码,但 HTTP/2 使用特殊的伪- 以 ':' 字符 (ASCII 0x3a) 开头的标题字段用于此目的。
那么为什么 HTTP/2 使用伪标头字段? HTTP/1.x 中的消息起始行有什么问题吗?
【问题讨论】:
从Google's introduction to HTTP/2借出一张图片
在这张图片中,您可以看到在第一个请求中,前两个标题行通常是这样的:
GET /resoure HTTP/1.1
Host: https://example.com
...
现在被拆分成这样的标题框架
:method: GET
:scheme: https
:host: example.com
:path: /resource
...
而其余的标题或多或少相同,除了都是小写字符。
HTTP/2 尝试尽可能减少负载大小。它还将压缩与上一个请求中发送的标头相同的标头和剥离标头,如链接图像的右侧部分所示。
在 HTTP/1.1 中,连续请求看起来像第一个初始请求,只是针对不同的资源:
GET /otherResource HTTP/1.1
Host: https://example.org
...
而在 HTTP/2 中,对同一服务器的连续请求只需要
:path: /otherResource
因为所有其他标头都已经可用,并且可以从之前缓存和索引的标头中恢复。
因此,这是一种优化,可进一步减少连续请求的负载。
【讨论】:
:key,或者只是想更多地关注这些变化。这些只是我的猜测。但他们肯定会使用它来减少连续请求的有效负载大小
HTTP/2 是新协议,采用二进制编码。
HTTP/2 中没有状态行,就像单个标头没有“行”一样。必须发明一种全新的方式来对 HTTP 请求的每个部分进行编码。
标题实际上是一个键值结构。与其为出现在 HTTP/1.1 请求的第一行的内容发明不同的编码,不如对这些内容使用相同的编码方法,从而使协议更简单。
毕竟,像“路径”和“http 方法”之类的东西已经在标头中,为什么不采用相同的方法将它们编码为常规标头。前面的 : 确保不会与现有的 HTTP/1.1 标头发生冲突,因为标头的名称永远不能包含 :。
所以 tl;dr 是:通过将来自 HTTP 请求和响应的第一行的信息编码为特殊的 HTTP 标头,协议可以更简单。
【讨论】: