我有一个小型 Web 应用程序,它由 Express.js 提供服务,并通过 Socket.io 连接到后端。为了公开,我使用 Nginx 作为反向代理,然后在最前面使用 Cloudflare。该应用程序依赖于关闭或重新加载时触发的 disconnect
事件来跟踪在线用户等。当通过 Nginx 和 Cloudflare 时,断开连接事件永远不会在后端触发。在本地开发时确实如此。
这是我的 Nginx 配置文件:
server {
listen 80;
server_name colab.gq;
server_name www.colab.gq;
location / {
proxy_pass http://localhost:3000;
proxy_set_header X-Forwarded-For $remote_addr;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/colab.gq/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/colab.gq/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
这是我的服务器端代码片段:
io.on('connection', (socket) => {
// Stuff here
socket.on('disconnect', () => {
console.log('disconnected!')
// Stuff that relies on the disconnect event
})
})
当用户关闭选项卡或重新加载页面时,断开连接事件应该触发,但通过 Nginx 和 Cloudflare 传递连接时永远不会触发。预先感谢您的帮助!
更新:似乎在重新加载/关闭断开事件几秒钟后终于注册。
最佳答案
您必须将升级 header 添加到 nginx 配置中的套接字 io 路径,如下所示,
location ~* \.io {
.. your configuration
proxy_pass http://localhost:3000;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
<小时/>
既然您要求扩展答案,您可能已经知道的第一件事是 socket.io 是一个在底层使用 Websockets 协议(protocol)的协议(protocol)(因此两者是相同的)。作为标准,Websockets 协议(protocol)和 HTTP 协议(protocol)都监听相同的端口 80 或 443。默认协议(protocol)是 HTTP,如果用户想要使用 Websockets 协议(protocol),他/她必须发送从 HTTP 到 WS 协议(protocol)的升级请求,并且有一些关键身份验证和步骤。
这就是为什么您需要将它们放入 nginx 配置中。
引用this如果您需要有关协议(protocol)升级机制的更多信息。
关于javascript - Socket.io 未通过 Cloudflare/Nginx 断开连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55325180/