Nginx 不执行 WebSocket 协议版本转换,仅透传 Upgrade 和 Connection 头并强制后端使用 HTTP/1.1;需设 proxy_http_version 1.1、proxy_set_header Upgrade $http_upgrade、proxy_set_header Connection $connection_upgrade,并通过 location 路径隔离 WebSocket 流量。

Nginx 本身不执行 WebSocket 协议版本转换,它不解析、不修改 WebSocket 帧,也不在 HTTP/1.1 和 HTTP/2 之间做协议“升级”或“降级”。所谓“处理协议版本转换”,实际是指确保 WebSocket 握手流程不被协议层干扰,核心是让客户端发起的 Upgrade: websocket 请求能完整、准确地抵达后端服务。
必须强制使用 HTTP/1.1 与后端通信
WebSocket 握手机制(101 Switching Protocols)仅定义在 HTTP/1.1 中。HTTP/2 已移除 Upgrade 和 Connection: upgrade 语义,Nginx 若与后端走 HTTP/2,握手必然失败。
- 必须显式设置:
proxy_http_version 1.1 - 不可写
proxy_http_version 2.0,即使前端用 HTTPS+HTTP/2 访问 wss:// - 若主 server 块启用了
http2(如listen 443 ssl http2),建议为 WebSocket 流量单独配置子域名(如ws.example.com),其 server 块中不加http2参数
Upgrade 和 Connection 头必须透传,且动态控制
Nginx 默认丢弃逐跳头(hop-by-hop headers),而 Upgrade 和 Connection 正是这类头。需主动透传:
-
proxy_set_header Upgrade $http_upgrade:保留客户端原始值(可能是websocket、mqtt等) -
proxy_set_header Connection $connection_upgrade:依赖 Nginx 内置变量$connection_upgrade(1.3.10+),它会自动判断——当$http_upgrade非空时设为"upgrade",否则设为"close" - ⚠️ 切勿写死
Connection "upgrade":会导致普通 HTTP 请求也被误升级,引发 400 错误
混合协议场景下的路径隔离更可靠
若后端同时提供 REST API(如 /api/)和 WebSocket 接口(如 /ws/):
- 推荐用
location路径分流,例如:-
location /api/ { proxy_pass http://backend; } -
location /ws/ { proxy_pass http://backend/ws/; ... WebSocket 专用配置 }
-
- 避免用
if判断请求类型做重定向或条件代理,可能破坏 WebSocket 握手的原子性
HTTP/2 前端 + WebSocket 后端的兼容要点
浏览器访问 wss://example.com 时,ALPN 协商会协商出 HTTP/2,但 Nginx 只需在与后端通信时降级为 HTTP/1.1 即可:
- 前端到 Nginx:支持 HTTP/2 或 HTTP/1.1 均可,不影响握手
- Nginx 到后端:必须为 HTTP/1.1,并透传升级头
- SSL 终止在 Nginx 时,务必加
proxy_set_header X-Forwarded-Proto $scheme,让后端识别真实协议为https,避免因 Origin 或协议校验失败而拒绝连接
不复杂但容易忽略











