结论
如果用户访问你的网站使用的是 HTTPS,前端 Socket.IO 也应该通过 HTTPS 域名连接。连接建立后,浏览器通常会将 WebSocket 升级为 WSS。
而在服务器内部,Nginx 可以继续使用 HTTP 转发到 Node.js:
浏览器 ── HTTPS / WSS ──> Nginx ── HTTP ──> Node.js
因此:
前端连接地址:
https://example.comWebSocket 实际连接:
wss://example.comNginx 到 Node.js:
http://127.0.0.1:3000
这两段连接使用不同协议是正常的。HTTPS 在 Nginx 处终止,Nginx 再通过 HTTP 与 Node.js 通信。
为什么前端不能直接连 HTTP?
假设你的网站是:
https://example.com
如果前端代码连接:
io("http://example.com");
浏览器可能会因为 混合内容(Mixed Content) 阻止连接:HTTPS 页面不应主动加载不安全的 HTTP 内容。
使用 WebSocket 时也一样:
HTTPS 页面应使用安全的
wss://HTTP 页面可以使用不加密的
ws://
使用 Socket.IO 时,通常不需要手动写 wss://。直接连接当前站点即可:
import { io } from "socket.io-client";
const socket = io();
如果需要写完整地址:
const socket = io("https://example.com");
Socket.IO 会根据 HTTPS 连接使用安全的 WebSocket(WSS)。它也可能先使用 HTTP 长轮询,再尝试升级为 WebSocket。
Node.js 示例
Node.js 服务可以继续运行在普通 HTTP 上。例如:
import { createServer } from "node:http";
import { Server } from "socket.io";
const httpServer = createServer();
const io = new Server(httpServer, {
cors: {
origin: "https://example.com",
methods: ["GET", "POST"],
},
});
io.on("connection", (socket) => {
console.log("客户端已连接:", socket.id);
});
httpServer.listen(3000, "127.0.0.1", () => {
console.log("Socket.IO 服务运行在 127.0.0.1:3000");
});
这里 Node.js 不需要配置 HTTPS 证书,因为 TLS 加密由 Nginx 负责。
如果前端与 Socket.IO 服务同域,通常可以省略 cors 配置;如果跨域,则需要将 origin 设置为实际的前端来源。
Nginx 配置示例
Nginx 需要正确转发 WebSocket 的 Upgrade 和 Connection 请求头。
可以在 http 配置块中添加:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
然后在 HTTPS 的 server 配置中设置代理:
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
location /socket.io/ {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}
Socket.IO 默认使用 /socket.io/ 路径,前后端路径需要一致。如果你修改了 Socket.IO 的 path,Nginx 的 location 也要相应修改。
修改 Nginx 配置后,可以检查并重新加载:
nginx -t
nginx -s reload
常见错误
1. HTTPS 页面连接 HTTP
io("http://example.com");
可能被浏览器以混合内容为由拦截。应改为:
io("https://example.com");
或者同域时直接写:
io();
2. Nginx 没有转发 WebSocket 请求头
如果缺少 Upgrade 和 Connection 配置,长轮询可能正常,但 WebSocket 升级可能失败。
3. Nginx 路径与 Socket.IO 路径不一致
默认路径是 /socket.io/。如果代理路径或 Socket.IO 的 path 配置不一致,客户端可能出现 404 或连接失败。
4. 超时时间过短
WebSocket 是长连接。如果代理读取超时时间太短,连接可能被 Nginx 关闭,可以根据业务设置合适的 proxy_read_timeout。
总结
你的部署方式可以保持为:
浏览器访问 HTTPS
↓
Nginx 处理 HTTPS/WSS
↓
Nginx 通过 HTTP 转发到 Node.js
所以,前端连接 HTTPS 域名,Node.js 后端仍然可以使用 HTTP。不要让 HTTPS 页面直接连接 http://,并确保 Nginx 配置了 WebSocket 升级头。