【发布时间】:2020-06-06 21:52:04
【问题描述】:
我有一个带有 JavaScript 客户端和 python 服务器的有效 socket.io 设置。 客户端基本上只有一行: WebSocket 握手期间出错:意外响应代码:404
socket = io.connect('');
服务器脚本可以在 https://github.com/miguelgrinberg/python-socketio/blob/master/examples/server/wsgi/app.py 找到 - 我在端口 5000 上运行服务器。
关于客户端和服务器,你可能只需要知道它们在我的 localhost apache 安装上运行良好,并且 socket.io 以 GET 请求开始并从那里升级到 websocket。成功的握手如下所示:
http://localhost:5000/socket.io/?EIO=3&transport=polling&t=N1kLfSx
http://localhost:5000/socket.io/?EIO=3&transport=polling&t=N1kLfTI&sid=70ddae8b36da4f0f8f9a851fa2c0121e
ws://localhost:5000/socket.io/?EIO=3&transport=websocket&sid=70ddae8b36da4f0f8f9a851fa2c0121e
现在我们有了一个 websocket,其余的通信都通过它运行。
我这两天正在尝试的是让示例在我的 Web 服务器上运行 - 所以我正在寻找一个有效的 apache https 配置,它将请求代理到端口 5000 上的后端服务器。
我尝试了几十种不同的配置,但没有一种能奏效——它们看起来都与此非常相似。 URL 重写部分是为了在初始握手成功后代理 websocket 连接。
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/socket.io [NC]
RewriteCond %{QUERY_STRING} transport=websocket [NC]
RewriteRule /(.*) ws://localhost:5000/$1 [P,L]
ProxyPass /socket.io/ http://localhost:5000/socket.io/
ProxyPassReverse /socket.io/ http://localhost:5000/socket.io/
Apache 确实将第一个 socket.io GET 请求转发给服务器,服务器回复:
ÿ0{"sid":"2efa0dbbce4c4eef958e70b393639610","upgrades":["websocket"],"pingTimeout":60000,"pingInterval":25000}ÿ42["my_response",{"data":"Connected","count":0}]ÿ40
然后一个 websocket 立即打开和关闭(代码 404)。然后客户端发送一个失败的 POST 请求(代码 400)。然后客户端从第 1 步重新开始:发出 GET 请求,获取新的会话 id...
(ÿXX 特殊字符也出现在有效的本地主机通信中 - 所以它们似乎属于那里)。
我做错了什么?
更新 - 接近解决方案!
我尝试了 socket.io 示例服务器的几个 Python 和 NodeJS 实现以及几个客户端脚本 - 它们都创建了相同的问题,这证实了我的论点,即 Apache 是问题所在。
我安装了 Nginx 并找到了一个终于可以工作的配置! 这些是神奇的线条:
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
我现在使用调试服务器打印所有收到的 HTTP 请求,以将 Nginx 请求与 Apache2 请求进行比较,目标是配置 Apache2 以传递与 Nginx 相同的标头。
最后一个挑战似乎是将 Nginx 配置行转换为 Apache2。听起来比它更容易......不过,这将是解决方案的关键。
【问题讨论】:
-
仅供参考:我尝试了在 stackoverflow(以及许多其他来源)上提出的每一个配置。我确实进行了自己的研究,并且确实查看了所有现有答案。
标签: socket.io apache2 reverse-proxy mod-proxy mod-proxy-wstunnel