nginx代理websocket需显式配置:启用http/1.1、透传upgrade和connection头、关闭缓冲、调大读写超时,且不缓存、不干预cors响应头。

要让 Nginx 正确代理 WebSocket 并维持长连接,核心不是“加个头就完事”,而是确保协议升级请求不被截断、连接不被超时中断、缓冲不干扰实时帧。Nginx 1.3.13+ 原生支持,但默认配置不启用 WebSocket 模式,必须显式声明。
透传 WebSocket 升级请求头
WebSocket 握手依赖两个关键逐跳(hop-by-hop)HTTP 头:Upgrade: websocket 和 Connection: Upgrade。Nginx 默认会丢弃或改写这些头,必须手动透传:
- proxy_http_version 1.1; —— HTTP/1.0 不支持 Upgrade,必须强制设为 1.1
- proxy_set_header Upgrade $http_upgrade; —— 将客户端原始 Upgrade 头原样转发($http_upgrade 是 Nginx 内置变量)
-
proxy_set_header Connection "upgrade"; —— 注意是固定字符串
"upgrade",不是$http_connection;因为 Connection 是逐跳头,不能继承客户端值(如 keep-alive)
禁用干扰长连接的默认行为
WebSocket 是全双工、长生命周期连接,Nginx 默认的缓冲和超时策略会主动切断它:
- proxy_buffering off; —— 关闭响应缓冲,避免 WebSocket 帧被暂存,导致延迟或粘包
- proxy_read_timeout 86400; —— 设为大值(如 24 小时),防止空闲期间 Nginx 主动关闭连接
- proxy_send_timeout 86400; —— 同理,保障服务端心跳或消息能顺利发出
- 不配置任何
proxy_cache_*指令 —— WebSocket 消息不可缓存,启用会直接失败
跨域处理交给后端,Nginx 不干预
浏览器只在 WebSocket 握手(HTTP GET → 101 Switching Protocols)阶段检查 CORS,且仅校验响应头。这个阶段的跨域头(如 Access-Control-Allow-Origin)必须由后端在 101 响应中返回:
- 不要在 Nginx 的 location 块里加
add_header Access-Control-Allow-Origin "*"; - Nginx 默认会透传后端返回的 101 响应头,无需额外配置
- 若后端未返回或被覆盖,可确认
proxy_pass_request_headers on;(默认已开启)
典型 location 配置示例
假设前端访问 /ws,后端 WebSocket 服务运行在 http://127.0.0.1:8080/ws:
location /ws {
proxy_pass http://127.0.0.1:8080/ws;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_buffering off;
proxy_read_timeout 86400;
proxy_send_timeout 86400;
}
保存后执行 nginx -t && nginx -s reload 生效。连接建立后,可通过浏览器控制台或 wscat 工具验证是否返回 101 状态码并持续通信。











