我在本地主机 127.0.0.1:8443 上构建了一个 nodeJS HTTP2 服务器。当我从 chrome 访问服务器时,转到 wireshark 并选择了环回适配器来捕获流量。我没有看到服务器在通信步骤中指定它是否支持 HTTP2。Chrome 只是将 HTTP 1.1 标识为通信协议。我想了解服务器何时会指定它支持的协议,以及当我将 nodeJS 服务器创建为 HTTP2 时,为什么在我的情况下通信没有通过 HTTP2 进行?
我经历过这样的事情:浏览器请求的HTTP版本和服务器响应的HTTP版本是如何确定的?但它没有帮助。
答案1
简短回答
为了安全的连接,在 TLS 协商期间通过 TLS-ALPN 协商执行 HTTP/2 的意图。然后在 TLS 协商完成后,双方交换 HTTP/2 连接前缀并从此时起继续执行 HTTP/2。
为了不安全连接,不再协商执行 HTTP/2 的意图(可能从未协商过)。客户端(浏览器)只需以某种方式知道服务器支持 HTTP/2,并且一旦不安全的 TCP 握手完成,客户端应使用 HTTP/2 连接前缀启动连接,服务器应使用其自己的 HTTP/2 连接前缀进行响应,并且双方应从此时起继续执行 HTTP/2。
长答案
HTTP/2 规范中涵盖了这一点,截至本文撰写时,其最新版本是 RFC 9113。您特别需要查看第 3 节“启动 HTTP/2”。
https://www.rfc-editor.org/rfc/rfc9113#starting
[注:HTTP/2 规范的早期版本提供了一种将不安全连接从 HTTP/1.1 升级到 HTTP/2 的方法,但这种方法从未得到广泛部署,现在已被弃用。我不知道哪些浏览器版本或服务器版本可能支持它,但它涉及客户端发出 HTTP/1.1 请求,其中包含一些特殊标头,表明它能够使用 HTTP/2,并希望服务器在可能的情况下将连接升级到 HTTP/2,然后服务器将以“HTTP/1.1 101 切换协议”响应进行响应,然后将连接的其余部分视为 HTTP/2(即通过与客户端交换 HTTP/2 连接前缀等)]
因此,如果您想建立不安全的 HTTP/2 连接,浏览器必须以某种方式知道服务器支持 HTTP/2,并且它只需建立 TCP 连接,然后以 HTTP/2 连接前言开始。
对于 TLS 保护的https://
URI,客户端指定它希望通过 TLS 应用层协议协商 (TLS-ALPN) 使用 HTTP/2,如RFC 7301。
一旦 TLS 协商完成,客户端和服务器都会各自发送一个 HTTP/2 连接前缀。
从您的数据包跟踪屏幕截图来看,您的浏览器似乎根本没有尝试执行 HTTP/2。即使您的端口号 8443 表明备用端口 443 表明使用 TLS,但我没有看到 TLS 发生,因此我推测 TLS-ALPN 没有发生,但也许它正在发生,但您的屏幕截图没有显示它。您的浏览器也不会使用 HTTP/2 连接前置词启动连接,而是使用 HTTP/1.1 连接启动它,甚至没有现已弃用的升级标头。因此,您可能需要弄清楚如何告诉您的浏览器将您的服务器视为 HTTP/2,这可能涉及在您的服务器上启用 TLS 和 TLS-ALPN,以便您的浏览器可以在 TLS 协商期间通过 TLS-ALPN 了解 HTTP/2 支持。