nginx未透传upgrade和connection头部导致404:必须在location块中配置proxy_http_version 1.1、proxy_set_header upgrade $http_upgrade、proxy_set_header connection "upgrade",并确保路径匹配与proxy_pass斜杠一致。

WebSocket 握手返回 404,基本可以断定是 Nginx 没转发 Upgrade 请求头,而不是后端服务没跑起来或路径写错了。
确认是否真由 Nginx 代理层拦截了 WebSocket 升级请求
浏览器控制台看到 WebSocket connection to 'ws://...' failed: Error during WebSocket handshake: Unexpected response code: 404,先别急着改后端路由。这个 404 很可能来自 Nginx 自己——它收到了一个带 Upgrade: websocket 和 Connection: Upgrade 的请求,但默认不识别、不透传,直接当普通 HTTP 路径处理,结果后端没注册该路径,就回了 404。
验证方法:
- 用
curl直接模拟握手请求,绕过浏览器缓存:curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" -H "Sec-WebSocket-Version: 13" http://your-domain.com/ws - 如果响应是
HTTP/1.1 404 Not Found(且无101 Switching Protocols),说明 Nginx 拦截了;如果是502或超时,则问题在后端连通性
检查 Nginx 配置中是否缺失关键 WebSocket 支持指令
仅靠 proxy_pass 不足以支持 WebSocket。必须显式启用 HTTP/1.1 并透传两个 hop-by-hop 头部。缺一不可。
以下三行必须同时出现在对应 location 块内(不是 http 或 server 全局):
-
proxy_http_version 1.1;—— HTTP/1.0 不支持Upgrade,必须升到 1.1 -
proxy_set_header Upgrade $http_upgrade;—— 把客户端的Upgrade头原样传给后端 -
proxy_set_header Connection "upgrade";—— 注意这里是固定字符串"upgrade",不是变量;Nginx 会据此判断这是升级请求
常见错误:把这三行写在 http 块里,或漏掉引号、写成 $connection_upgrade 却没定义 map,或误写为 Connection $http_connection。
检查 location 路径匹配与 proxy_pass 尾部斜杠是否一致
WebSocket 路径转发对斜杠极其敏感。比如前端连接 ws://example.com/api/ws,而配置是:
-
location /api/ws { proxy_pass http://backend; }→ 后端收到的是/api/ws,若后端只监听/ws,就会 404 -
location /api/ws { proxy_pass http://backend/; }→ 斜杠结尾会剥离/api/ws,后端收到/,也可能 404 - 正确写法通常是:
location /api/ws { proxy_pass http://backend/ws; },确保路径精准对齐
更稳妥的做法是统一用前缀匹配 + 显式重写:location ^~ /api/ws { rewrite ^/api/(.*)$ /$1 break; proxy_pass http://backend; }
检查是否被其他配置覆盖或引入冲突文件
Nginx 加载配置时,include 的顺序和重复 server_name 可能导致某段配置根本没生效。
- 运行
nginx -T输出完整生效配置,搜索你的location块,确认它确实被加载且未被更高优先级的正则location ~覆盖 - 检查是否有残留备份文件如
/etc/nginx/conf.d/default.conf.rpmsave被意外include,造成 server 块重复或冲突 - 用
grep -r "server_name" /etc/nginx/conf.d/确认域名只在一个server块中定义
真正容易被忽略的点:即使所有配置语法正确,只要 proxy_set_header Connection 写成了小写 connection,或用了中文引号,Nginx 就会静默忽略该行——错误日志里也不会报,但 WebSocket 就是不通。











