浏览器如何知道在发送请求时应该使用哪个版本的 HTTP?

浏览器如何知道在发送请求时应该使用哪个版本的 HTTP?

当浏览器首次向服务器发送请求时,它如何决定应应用哪个版本的 HTTP?HTTPRFC 规范说:

HTTP 客户端应该发送一个请求版本,该版本应等于客户端至少有条件遵守的最高版本

但从我在 Chrome 检查器中的实验来看,Chrome 在向某些网站发送请求时使用 HTTP 2,但在其他情况下也会使用 HTTP 1.1。

我想知道 Chrome 如何知道应该使用哪个版本的 HTTP 请求?我知道服务器应该使用它支持的最高版本的 HTTP 进行响应,那么 Chrome 是否会默认使用 http2 向每个网站发送第一个请求,然后保存网站支持的 HTTP 版本并在之后使用该版本?

如能得到任何解释我将不胜感激。

答案1

HTTP/1.x

HTTP/1.1 和 HTTP/1.0 都使用兼容的请求格式。在第一次请求后,服务器的响应将标明支持的版本,加上诸如“连接:保持活动”之类的标题,指示可以使用哪些功能。

HTTP/2

浏览器已决定仅通过 TLS 连接支持 HTTP/2。这允许它们使用名为 ALPN(应用层协议协商)的新 TLS 功能。

当 Chrome 建立 TLS 连接时,它会在 TLS 握手过程中发送支持的协议列表(http/1.1h2),并且服务器会使用它希望使用的协议进行响应 - 例如“h2”,表示它现在需要 HTTP/2。

如果服务器根本没有返回 ALPN 扩展,浏览器会假定它仅支持 HTTP/1.x。(这就是为什么在服务器上启用 HTTP/2 支持需要升级 OpenSSL 的原因。)


HTTP/2 协议本身支持使用 HTTP 的纯文本连接升级机制。在大多数情况下,第一个请求必须是 HTTP/1.1,并且Upgrade:标头再次列出客户端想要切换到的协议。

响应也将是 HTTP/1.1,要么是“101 切换协议”,表示服务器现在在相同连接上需要 HTTP/2,要么是其他内容,表示不支持 HTTP/2。

浏览器不会以这种方式使用 HTTP 升级,它们只是不支持没有 TLS 的 HTTP/2。(但是,Apache HTTPD Web 服务器可以配置为接受'h2c' 连接用于测试。)

HTTP/3

HTTP/3 使用不同的传输协议(QUIC 与 TCP),因此无法进行内联升级。浏览器不知道服务器是否支持 QUIC,因此它仍会建立初始 TCP 连接,并使用上述 TLS ALPN 协商 HTTP/1.1 与 HTTP/2。

升级到 HTTP/3 实际上是由服务器发起的——服务器在其 HTTP 响应中发送Alt-Svc 标头(或 HTTP/2 中的特殊 ALTSVC 帧)表示它在指定的 UDP/QUIC 端口上支持 HTTP/3。浏览器可能会遵循该建议并尝试建立 QUIC 连接,如果成功则关闭 TCP 连接。

答案2

我想进一步阐述u1686_grawity 的回答

浏览器如何使用 HTTP/3 发出第一个请求?

2020 年,一项新的互联网标准草案已经发布,它定义了一种让浏览器决定即使对于第一个请求也使用哪个 HTTP 版本的方法。

这种方式是使用新的HTTPSSVCB DNS record types.

现已发布为RFC 9460

例子

类似这样的条目:

example.com 3600 IN HTTPS 1 . alpn=”h3,h2”

...宣传对 example.com 来源的 HTTP/3 和 HTTP/2 协议的支持。

此外,SVCBDNS记录可以使浏览器只需执行一次DNS查询即可了解协议以及目标IP。您可以在Cloudflare 的博客文章

浏览器支持

支持这些条目的浏览器是:

  • Chrome,自v102(2022 年 5 月上映),
  • Firefox,自v92(2021 年 7 月发布),
  • Safari,自v14(于 2020 年 9 月发布),但从 Safari 17.2(2023 年 12 月)开始,该浏览器对 HTTP/3 的整体支持处于“实验性”状态,并且每次仅对约 50% 的用户启用

更多信息

相关内容