Socket.io请求路径需精准匹配/socket.io/(末尾斜杠不可省略),proxy_pass也须以斜杠结尾;必须配置proxy_http_version 1.1及Upgrade、Connection头以支持WebSocket升级;CORS应由后端统一处理,Nginx避免对WebSocket请求重复设置Access-Control-Allow-Origin。

明确 Socket.io 的请求路径特征
Socket.io 客户端默认会发起两类关键请求:一是获取 /socket.io/ 路径下的 JS 文件(如 /socket.io/socket.io.js),二是建立 WebSocket 连接时尝试多个升级路径,包括 /socket.io/?EIO=4&transport=polling 和 /socket.io/?EIO=4&transport=websocket。Nginx 必须同时覆盖这些路径,否则会出现 404 或连接失败。
location 块必须以斜杠结尾并精准匹配
配置时 location /socket.io/ 中的末尾斜杠不可省略。若写成 location /socket.io(无斜杠),Nginx 会错误匹配到 /socket.iocustom 这类路径,导致代理异常。同时,proxy_pass 的值也需以斜杠结尾,例如:proxy_pass http://127.0.0.1:3000/;
这样才能保证路径重写正确——访问 /socket.io/xxx 时,实际转发为 http://127.0.0.1:3000/xxx,而不是拼接成 http://127.0.0.1:3000/socket.io/xxx。
启用 WebSocket 协议升级支持
WebSocket 连接依赖 HTTP 协议升级,Nginx 默认不透传 Upgrade 和 Connection 头,必须显式设置:
proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";
跨域响应头应按规范分离处理
不要在 location /socket.io/ 块中简单加 add_header Access-Control-Allow-Origin "*"。因为 OPTIONS 预检请求和普通请求共用同一 location,而浏览器对 WebSocket 的 CORS 检查只发生在首次 polling 请求,且不允许重复设置 Access-Control-Allow-Origin(否则报错“CORS header ‘Access-Control-Allow-Origin’ cannot be used”)。推荐做法是:
- 后端(如 socket.io Server)开启
cors: { origin: true },由它统一返回正确头 - Nginx 仅负责代理和协议升级,不干预 CORS 头
- 若必须由 Nginx 控制,只对非 WebSocket 的初始 polling 请求添加头,并用
if ($http_upgrade != "websocket") { ... }判断,避免污染 upgrade 流程


















