websocket握手失败的核心原因是nginx默认丢弃upgrade头且不处理connection: upgrade,导致http请求无法升级为websocket协议;必须配置proxy_http_version 1.1、proxy_set_header upgrade $http_upgrade、proxy_set_header connection "upgrade"三行指令。

这不是单一原因导致的报错,而是前端发起 WebSocket 握手请求后,服务端或中间链路拒绝、中断或未响应升级协议的结果。核心问题永远在「握手阶段」——HTTP 请求没成功切换成 WebSocket 协议。
为什么 Nginx 反向代理下 wss 连接总失败?
Nginx 默认把 Upgrade 头当普通请求头丢弃,也不处理 Connection: upgrade,导致 WebSocket 握手卡在 400/426/502 等状态码。
- 必须在
location块里显式添加三行关键配置:proxy_http_version 1.1、proxy_set_header Upgrade $http_upgrade、proxy_set_header Connection "upgrade" - 如果用了
proxy_redirect或重写规则,确保路径末尾不带多余斜杠(比如/ws/和/ws后端路由可能不一致) - 若启用 HTTPS,Nginx 必须已加载有效证书;否则浏览器直接拒绝建立
wss连接,控制台甚至不会发出请求
为什么本地开发时 ws://localhost 失败,但线上 wss 正常?
常见于 Vue/React 项目用 webpack-dev-server 或 vite 启动时,前端代码试图连后端 WebSocket 服务,但开发服务器没透传 WebSocket 流量。
- Vue CLI 项目:检查
vue.config.js中devServer.client.webSocketURL是否指向正确地址,例如'ws://localhost:8080/ws',不能写成'auto://'或留空 - Vite 项目:确认
server.host设为true或具体 IP,并在server.proxy中为 WebSocket 路径加ws: true选项 - 注意:Chrome 对
ws://连接有更宽松策略,但 Safari 和部分企业环境会拦截非https://页面发起的wss://,反之亦然
为什么 telnet 能通、curl 能拿到响应,但 WebSocket 就是连不上?
说明 TCP 层通畅,但协议层被拦住了——大概率是防火墙或安全组只放行了端口,却没允许 WebSocket 所需的「连接升级」行为。
- 云服务器(如阿里云、腾讯云):必须在「安全组」中放行对应端口(如
8080、8282),且协议选TCP - Linux 本地防火墙(
ufw/firewalld):同样要显式开放端口,ufw allow 8080/tcp,不能只依赖 Docker 的 iptables 自动转发(Docker 容器暴露端口 ≠ 主机防火墙放行) - 宝塔面板用户:别只看「安全」页的端口列表,还要进「软件管理 → Nginx → 设置 → 配置修改」确认反向代理配置是否生效,重启 Nginx 比重启面板更关键
真正容易被忽略的是:WebSocket 握手失败时,浏览器 Network 面板里那个 WS 请求的状态码,往往比控制台报错文字更有价值。403 是权限拦截,400 是参数或协议头缺失,502 是 Nginx 没连上后端,而「failed」本身什么都没说——得先让它变成一个具体状态码,才能往下查。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











