#36833·deno

HTTP/2 服务器: 为 WebSocket-over-h2 (RFC 8441 服务器端) 广告 SETTINGS_ENABLE_CONNECT_PROTOCOL

作者: bixu创建于 2026年9月14日更新于 2026年9月14日

摘要

Deno 问题 #11261 ("支持通过 H2 进行 WebSocket") 已于 2026-06-03 关闭,涵盖了 RFC 8441 中的 客户端 部分。服务器端尚未实现: Deno.serve 的 HTTP/2 后端从未发布 SETTINGS_ENABLE_CONNECT_PROTOCOL=1,因此支持扩展 CONNECT WebSocket 协议的客户端在 ALPN 协商 h2 时会出现不透明的协议错误。

后果: 基于 Deno 的服务器加上基于 Deno 的 WebSocket 客户端无法在 h2 上进行互操作。如果 ALPN 选择 h2,客户端的 WebSocket 升级将失败;如果 ALPN 选择 http/1.1,则会正常工作。

重现

服务器: 任何使用 Deno.serve 在 TLS 上的默认 ALPN (提供 h2, http/1.1) 并使用处理器中的 Deno.upgradeWebSocket 的服务器。

客户端: 当前版本的 Deno 内置 WebSocket 通过 wss:// 与该服务器建立连接。

结果: 客户端发出 流错误接收: 检测到不具体的协议错误。h2 扩展 CONNECT 与 :protocol: websocket 从未完成,因为服务器没有发送 SETTINGS_ENABLE_CONNECT_PROTOCOL=1

如果服务器被迫从 ALPN 中删除 h2,则才会正常工作。

通过源代码进行验证

ext/http/http_next.rs: 没有引用 enable_connect_protocolEnableConnectProtocol:protocol。h2 服务器从未发布该设置。

客户端端正常工作: 关闭问题 #11261 引用了修复,确认在 ALPN 选择 h2 时扩展 CONNECT 将被发送。

影响

任何使用 TLS 并需要 WebSocket 的 Deno 服务器-Deno 客户端拓扑都必须从服务器 ALPN 中删除 h2(每个客户端 Pod 中的反向代理侧车)或通过带外标志强制使用 http/1.1。今天在生产环境中我们遇到了此问题,通过为每个客户端 Pod 配置一个 nginx 侧车来解决了问题。

请求

Deno.serve 中,当处理器调用 Deno.upgradeWebSocket 时,将 SETTINGS_ENABLE_CONNECT_PROTOCOL=1 添加到 h2 SETTINGS 帧中。接受带 :protocol: websocket 的扩展 CONNECT 并将其路由到相同的升级处理器。

或者,如果更喜欢运行时标志:在 Deno.serve 上暴露选项,例如 { enableConnectProtocol: true }

相关

  • 关闭: #11261 (客户端端)。
  • RFC 8441: 通过 HTTP/2 进行 WebSocket 启动。

我很乐意测试修复或提供有用的更小的重现。