DEBUG.WIKI
雨云;给项目一台云服务器
晚安云;香港 CN2 ¥15/月
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →

Actix WebSocket 已回 101,客户端却报缺少 Connection: upgrade

actix-http 3.13.0 可能把 WebSocket 升级响应改成 Connection: close。3.13.1 正式修正分派路径,核对锁文件和真实握手,不只在 handler 补头。

Actix Web 的 WebSocket 路由此前能连接,更新锁文件后客户端却报 MissingConnectionUpgradeHeader,或提示 No "Connection: upgrade" header。服务端甚至已经返回 101,但响应里的 Connection 被写成了 close。

如果依赖变化是 actix-http 从 3.12.1 升到 3.13.0,应先检查这次 HTTP/1 升级响应回归。它可以在本机直连时触发,不需要反向代理参与;不能只因为错误涉及 Upgrade,就立即修改 Nginx。

101 响应仍被后续分派逻辑改成关闭

3.13.0 增加了对未读请求正文的提前响应关闭处理。WebSocket 升级时,请求 payload 仍保持打开,后续发送响应的逻辑可能将它当成普通提前结束的请求,把连接类型改为 Close。

因此在 actix_ws::handle() 返回后手动加入 Connection: upgrade,或再次将 response 标记为 Upgrade,未必有效:后面的分派仍可能覆盖它。看到 handler 中的响应头正确,不代表最终送到客户端的头相同。

先核对真正参与构建的底层版本,而不是只看 actix-web 的版本号:

cargo tree -i actix-http

工作区里可能同时存在不同版本。若 Cargo 要求消除歧义,应按输出指定具体包版本,再确认服务二进制实际使用哪一支。

采用包含排除升级响应处理的正式版本

actix-http 3.13.1 已正式发布,发送响应时会先排除升级响应,再决定是否因未读 payload 关闭普通 HTTP/1 连接。这项修正保留普通请求的关闭保护,没有要求业务自行删除这一逻辑。

在依赖约束允许时,可用下面的命令把相关锁定项更新到这个已确认包含修正的版本:

cargo update -p actix-http --precise 3.13.1

3.13.1 是这里确认修复的版本,不是让已经使用更高兼容版本的项目回退。更新前保留原 Cargo.lock,核对 Rust 工具链、actix-web、actix-ws 与其他依赖的兼容范围;若约束不允许选择这版,先解决对应依赖关系,而不是手改锁文件校验信息。

构建和部署后仍要核对运行产物。只更新本机锁文件,没有替换实际服务,线上握手路径不会改变。

直连和代理入口分别验收

在获准的测试入口,检查 HTTP/1 握手最终是否为 101,Connection、Upgrade 等字段是否满足协议,再验证真实文本或二进制消息、关闭握手和任务退出。仅看到 101,不能证明升级后的双向会话已经可用。

有反向代理时,再通过原代理入口检查相同路由。直连正常而代理失败,才继续定位代理的升级转发配置;直连就返回 close 时,不能拿增加代理 header 掩盖底层版本问题。

如果当前版本已经包含这项修正,仍出现相同错误,需重新核对认证拒绝、路由、响应状态和实际头字段。普通 401、404 或应用主动关闭,也可能让 WebSocket 客户端报握手失败,不应一概归到 3.13.0 的回归。