WebSocket 连接握手中缺少 Sec-WebSocket-Key

问题描述 投票:0回答:2

从昨天开始,我们就遇到了 WebSocket 连接问题。基于 chromium 的浏览器和 Firefox 在连接期间不会将

Sec-WebSocket-Key
添加到标头中。我们使用标准的
new WebSocket()
来连接服务器。

缺少标题

Sec-WebSocket-Key
标题

有趣的是,当我打开一个新的隐身窗口时,我可以创建一个连接,但在一些

fetch()
请求之后,如果我尝试建立另一个连接,它将失败 - 缺少
Sec-Websocket-Key
标头。

  1. 首次 WebSocket 连接 - 成功

  2. 获取请求 - 应用程序运行状况

  3. 获取请求后 WebSockect 连接失败 第二个 WebSocket 连接 - 丢失

    Sec-WebSocket-Key

Nginx 配置

/ws

    location ^~ /ws {                                                                                                                      
        proxy_http_version 1.1;                                                                     
        proxy_set_header Upgrade $http_upgrade;                     
        proxy_set_header Connection "upgrade";                                                               
        proxy_set_header Host $http_host;                           
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;            
        proxy_pass http://backend;  
    }                           

有人遇到过类似的问题吗?

已在 Windows、Linux 和 Mac 上检查 Google Chrome 版本 96.0.4664.93 和 Firefox 95.0.1。

MacOS 和 Safari 均可使用。

firefox websocket chromium
2个回答
1
投票

问题可能出在 Firefox 和 Chrome 中的 HTTP2 实现(Safari 工作正常)。我们挖掘了三天,终于意识到禁用 HTTP2 后问题就消失了。

这是DigitalOcean技术支持的回复:

我们最近启用了对 HTTP2 上的 Websocket 的支持 (RFC 8441)。 这增加了对浏览器重用现有 HTTP2 连接的支持 并将允许通过 HTTP2 建立 WebSocket 连接隧道 溪流。作为立即修复的一部分,我们已禁用此功能 通知浏览器通过 HTTP1.1 创建 Websocket 的功能 (RFC 6455)。我们相信该错误实际上存在于 Chrome/Firefox 中,但是 需要进一步测试来找出问题所在。据我们所知 LB 不是问题,因为浏览器不包括 所需的标头 Sec-WebSocket-Key。


0
投票

我们也遇到了类似的问题。

  • 我们的 CDN 正在向客户端返回
    SETTINGS_ENABLE_CONNECT_PROTOCOL:1
    ,这表明支持基于 HTTP/2 (RFC 8441) 的 WebSockets。
  • 因此 Chrome 尝试通过 HTTP/2 连接 WebSocket 但失败,因为我们的后端服务不支持 RFC 8441。
      在 RFC 8441 中,
    • Sec-WebSocket-Key
      非必需。问题是 Chrome 尝试通过 HTTP/2 使用 WebSocket。
      Sec-WebSocket-Key
      缺失只是一方面。
  • 该错误偶尔会发生,因为:
    • 当 HTTP/3 可用时,Chrome 尝试建立 HTTP/2 和 HTTP/3 连接,并且实际上会使用“赢得比赛”的连接。
    • 当 HTTP/2 获胜时,连接失败,如上所述。
    • 当 HTTP/3 获胜时,使用 HTTP/1.1 上的 WebSockets 并且连接成功。
      • 没有深入研究这个。可能我们的 CDN 没有通过 HTTP/3 发送
        SETTINGS_ENABLE_CONNECT_PROTOCOL:1
  • 它在 Safari 中有效,因为 Safari 不支持 HTTP/2 上的 WebSockets,并且始终使用 HTTP/1.1。

我们联系了我们的 CDN 提供商,他们禁用了

SETTINGS_ENABLE_CONNECT_PROTOCOL:1
,错误就不再发生了。

© www.soinside.com 2019 - 2024. All rights reserved.