简体   繁体   English

socket.io https apache2 的代理配置

[英]socket.io https proxy config for apache2

I have a working socket.io setup with a JavaScript-client and a python-server.我有一个有效的 socket.io 设置,带有 JavaScript 客户端和 python 服务器。 The client is basically just one line: Error during WebSocket handshake: Unexpected response code: 404客户端基本上只有一行:Error during WebSocket handshake: Unexpected response code: 404

socket = io.connect('');

The server script can be found at https://github.com/miguelgrinberg/python-socketio/blob/master/examples/server/wsgi/app.py - I'm running the server on port 5000.服务器脚本可以在https://github.com/miguelgrinberg/python-socketio/blob/master/examples/server/wsgi/app.py找到——我在端口 5000 上运行服务器。

All you probably have to know about client and server is that they work great on my localhost apache installation and that socket.io starts with a GET requests and upgrades to a websocket from there.关于客户端和服务器,您可能只需要知道它们在我的本地主机 apache 安装上运行良好,并且 socket.io 从 GET 请求开始并从那里升级到 websocket。 This is how a successfull handshake looks like:这是成功握手的样子:

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

Now we have a websocket and the rest of the communication is running through that.现在我们有一个 websocket 和 rest 的通信正在运行。

What I'm trying for two days now is to get the example running on my web server - so I'm looking for a working apache https config that proxies the requests to my backend server on port 5000.我这两天正在尝试的是让示例在我的 web 服务器上运行 - 所以我正在寻找一个有效的 apache https 配置,该配置将请求代理到端口 5000 上的后端服务器。

I tried dozens of variations of configurations and none of them works - they all look very similar to this.我尝试了数十种配置变体,但没有一种起作用——它们看起来都与此非常相似。 The URL-rewriting part is meant to proxy the websocket connection once the initial handshake succeeded. 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 does forward the first socket.io GET request to the server, the server replies: Apache确实将第一个socket.io GET请求转发给服务器,服务器回复:

    ÿ0{"sid":"2efa0dbbce4c4eef958e70b393639610","upgrades":["websocket"],"pingTimeout":60000,"pingInterval":25000}ÿ42["my_response",{"data":"Connected","count":0}]ÿ40

Then a websocket is opened and closed again right away (code 404).然后立即打开并再次关闭 websocket(代码 404)。 Then the client sends a POST request which fails (code 400).然后客户端发送失败的 POST 请求(代码 400)。 Then the client starts all over again with step 1: making a GET request, getting a new session id...然后客户端从第 1 步重新开始:发出 GET 请求,获取新的 session id ...

(The ÿXX special characters also appear in the working localhost communication - so they seem to belong there). ÿXX特殊字符也出现在工作的本地主机通信中 - 所以它们似乎属于那里)。

What am I doing wrong?我究竟做错了什么?

UPDATE - getting close to a solution!更新 - 接近解决方案!

I tried several Python and NodeJS implementations of an socket.io example server as well as several client scripts - all of them created the same problem which confirmed my thesis that Apache is the problem.我尝试了几个 Python 和 socket.io 示例服务器的 NodeJS 实现以及几个客户端脚本 - 所有这些都产生了相同的问题,这证实了我的论文 Apache 是问题所在。

I installed Nginx and found a configuration that finally worked: These are the magic lines:我安装了 Nginx 并找到了一个最终有效的配置:这些是神奇的线条:

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

I'm now using a debug-server that prints all received HTTP requests to compare the Nginx requests to the Apache2 requests with the goal to configure Apache2 to pass the same headers as Nginx.我现在正在使用调试服务器打印所有收到的 HTTP 请求,以将 Nginx 请求与 Apache2 请求进行比较,目的是配置 Apache2 以传递与 Nginx 相同的标头。

The last challenge seems to be translating the Nginx config lines to Apache2. Sounds easier than it is.. that will be the key to the solution, though.最后一个挑战似乎是将 Nginx 配置行转换为 Apache2。听起来比实际更容易……但这将是解决方案的关键。

Finally: After a week of research I finally found a working solution:最后:经过一周的研究,我终于找到了一个可行的解决方案:

I put this code into the Section of my Apache2 config:我将此代码放入我的 Apache2 配置的部分:

        ProxyRequests off
        ProxyVia on
        RewriteEngine On

        RewriteEngine On
        RewriteCond %{HTTP:Connection} Upgrade [NC]
        RewriteCond %{HTTP:Upgrade} websocket [NC]
        RewriteRule /(.*) ws://127.0.0.1:8080/$1 [P,L]

        ProxyPass               / http://127.0.0.1:5000/
        ProxyPassReverse        / http://127.0.0.1:5000/

There's a million configurations out there and I tried them all - this is the only one that worked for me.有一百万种配置,我都试过了——这是唯一适合我的配置。 The problem was, that Apache2 didn't forward the "Upgrade=websocket" and "Connection=upgrade" headers.问题是,Apache2 没有转发“Upgrade=websocket”和“Connection=upgrade”标头。 The given rewrite commands make Apache2 add these headers to the proxied connection.给定的重写命令使 Apache2 将这些标头添加到代理连接。

While researching this I first found a working Nginx configuration which I then translated to Apache2. So if you have that problem with Nginx, you can use this here:在研究这个问题时,我首先找到了一个有效的 Nginx 配置,然后我将其转换为 Apache2。因此,如果你对 Nginx 有这个问题,你可以在这里使用它:

        location / {
                proxy_pass http://127.0.0.1:5000/;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
                proxy_set_header Host $host;
                proxy_cache_bypass $http_upgrade;
        }

This little NodeJS TCP Server helped me a lot with debugging the HTTP headers: https://riptutorial.com/node.js/example/22405/a-simple-tcp-server这个小 NodeJS TCP 服务器在调试 HTTP 标头方面帮了我很多: https://riptutorial.com/node.js/example/22405/a-simple-tcp-server

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM