node.js WebSockets 和 Apache 代理:如何配置 mod_proxy_wstunnel?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27526281/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WebSockets and Apache proxy : how to configure mod_proxy_wstunnel?
提问by Basj
I have :
我有 :
Apache(v2.4) on port 80 of my server forwww.domain1.com, with mod_proxyand mod_proxy_wstunnelenablednode.js + socket.ioon port 3001 of the same server.
Apache(v2.4) 在我的服务器的端口 80 上www.domain1.com,启用了mod_proxy和mod_proxy_wstunnelnode.js + socket.io在同一台服务器的 3001 端口上。
Accessing www.domain2.com(with port 80) redirects to 2. thanks to the method described here. I have set this in the Apache configuration:
www.domain2.com由于这里描述的方法,访问(使用端口 80)重定向到 2 。我已经在 Apache 配置中设置了这个:
<VirtualHost *:80>
ServerName www.domain2.com
ProxyPass / http://localhost:3001/
ProxyPassReverse / http://localhost:3001/
ProxyPass / ws://localhost:3001/
ProxyPassReverse / ws://localhost:3001/
</VirtualHost>
It works for everything, except the websocket part : ws://...are not transmitted like it should by the proxy.
它适用于所有内容,除了 websocket 部分:ws://...不会像代理那样传输。
When I access the page on www.domain2.com, I have:
当我访问 上的页面时www.domain2.com,我有:
Impossible to connect ws://www.domain2.com/socket.io/?EIO=3&transport=websocket&sid=n30rqg9AEqZIk5c9AABN.
Question: How to make Apache proxy the WebSockets as well?
问题:如何让 Apache 也代理 WebSockets?
回答by Basj
I finally managed to do it, thanks to this topic.
多亏了这个话题,我终于做到了。
TODO:
去做:
1) Have Apache 2.4 installed (doesn't work with 2.2), and do:
1) 安装 Apache 2.4(不适用于 2.2),然后执行:
a2enmod proxy
a2enmod proxy_http
a2enmod proxy_wstunnel
2) Have nodejsrunning on port 3001
2)nodejs运行在 3001 端口
3) Do this in the Apache config
3)在Apache配置中执行此操作
<VirtualHost *:80>
ServerName www.domain2.com
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/socket.io [NC]
RewriteCond %{QUERY_STRING} transport=websocket [NC]
RewriteRule /(.*) ws://localhost:3001/ [P,L]
ProxyPass / http://localhost:3001/
ProxyPassReverse / http://localhost:3001/
</VirtualHost>
Note: if you have more than one service on the same server that uses websockets, you might want to do thisto separate them.
注意:如果您在使用 websockets 的同一台服务器上有多个服务,您可能需要这样做以将它们分开。
回答by cdauth
Instead of filtering by URL, you can also filter by HTTP header. This configuration will work for any web applications that use websockets, also if they are not using socket.io:
除了按 URL 过滤,您还可以按 HTTP 标头过滤。此配置适用于任何使用 websockets 的 Web 应用程序,即使它们不使用 socket.io:
<VirtualHost *:80>
ServerName www.domain2.com
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /(.*) ws://localhost:3001/ [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteRule /(.*) http://localhost:3001/ [P,L]
ProxyPassReverse / http://localhost:3001/
</VirtualHost>
回答by Sergey
May be will be useful. Just all queries send via ws to node
可能会有用。只是所有查询都通过 ws 发送到节点
<VirtualHost *:80>
ServerName www.domain2.com
<Location "/">
ProxyPass "ws://localhost:3001/"
</Location>
</VirtualHost>
回答by Erik Koopmans
As of Socket.IO 1.0 (May 2014), all connections begin with an HTTP polling request (more info here). That means that in addition to forwarding WebSocket traffic, you need to forward any transport=pollingHTTP requests.
从 Socket.IO 1.0(2014 年 5 月)开始,所有连接都以 HTTP 轮询请求开始(更多信息请点击此处)。这意味着除了转发 WebSocket 流量之外,您还需要转发任何transport=pollingHTTP 请求。
The solution below should redirect all socket traffic correctly, without redirecting any other traffic.
下面的解决方案应该正确重定向所有套接字流量,而不重定向任何其他流量。
Enable the following Apache2 mods:
sudo a2enmod proxy rewrite proxy_http proxy_wstunnelUse these settings in your *.conf file (e.g.
/etc/apache2/sites-available/mysite.com.conf). I've included comments to explain each piece:<VirtualHost *:80> ServerName www.mydomain.com # Enable the rewrite engine # Requires: sudo a2enmod proxy rewrite proxy_http proxy_wstunnel # In the rules/conds, [NC] means case-insensitve, [P] means proxy RewriteEngine On # socket.io 1.0+ starts all connections with an HTTP polling request RewriteCond %{QUERY_STRING} transport=polling [NC] RewriteRule /(.*) http://localhost:3001/ [P] # When socket.io wants to initiate a WebSocket connection, it sends an # "upgrade: websocket" request that should be transferred to ws:// RewriteCond %{HTTP:Upgrade} websocket [NC] RewriteRule /(.*) ws://localhost:3001/ [P] # OPTIONAL: Route all HTTP traffic at /node to port 3001 ProxyRequests Off ProxyPass /node http://localhost:3001 ProxyPassReverse /node http://localhost:3001 </VirtualHost>I've included an extra section for routing
/nodetraffic that I find handy, see herefor more info.
启用以下 Apache2 模组:
sudo a2enmod proxy rewrite proxy_http proxy_wstunnel在您的 *.conf 文件(例如
/etc/apache2/sites-available/mysite.com.conf)中使用这些设置。我已经包含注释来解释每个部分:<VirtualHost *:80> ServerName www.mydomain.com # Enable the rewrite engine # Requires: sudo a2enmod proxy rewrite proxy_http proxy_wstunnel # In the rules/conds, [NC] means case-insensitve, [P] means proxy RewriteEngine On # socket.io 1.0+ starts all connections with an HTTP polling request RewriteCond %{QUERY_STRING} transport=polling [NC] RewriteRule /(.*) http://localhost:3001/ [P] # When socket.io wants to initiate a WebSocket connection, it sends an # "upgrade: websocket" request that should be transferred to ws:// RewriteCond %{HTTP:Upgrade} websocket [NC] RewriteRule /(.*) ws://localhost:3001/ [P] # OPTIONAL: Route all HTTP traffic at /node to port 3001 ProxyRequests Off ProxyPass /node http://localhost:3001 ProxyPassReverse /node http://localhost:3001 </VirtualHost>我已经包含了一个
/node我觉得方便的用于路由流量的额外部分,请参阅此处了解更多信息。
回答by Otto Paulsen
With help from these answers, I finally got reverse proxy for Node-RED running on a Raspberry Pi with Ubuntu Mate and Apache2 working, using this Apache2 site config:
在这些答案的帮助下,我终于获得了在 Raspberry Pi 上运行的 Node-RED 反向代理,使用 Ubuntu Mate 和 Apache2 工作,使用这个 Apache2 站点配置:
<VirtualHost *:80>
ServerName nodered.domain.com
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /(.*) ws://localhost:1880/ [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteRule /(.*) http://localhost:1880/ [P,L]
</VirtualHost>
I also had to enable modules like this:
我还必须启用这样的模块:
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_wstunnel
回答by Leon
For me it works after adding only one linein httpd.conf as below (bold line).
对我来说,它在 httpd.conf 中只添加一行后就可以工作了,如下所示(粗体)。
<VirtualHost *:80>
ServerName: xxxxx
#ProxyPassReverse is not needed
ProxyPass /log4j ws://localhost:4711/logs
<VirtualHost *:80>
Apache version is 2.4.6 on CentOS.
CentOS 上的 Apache 版本是 2.4.6。
回答by Anwaarullah
My setup:
我的设置:
- Apache 2.4.10 (running off Debian)
- Node.js (version 4.1.1) App running on port 3000 that accepts WebSockets at path
/api/ws
- Apache 2.4.10(脱离 Debian)
- Node.js(版本 4.1.1)在端口 3000 上运行的应用程序在路径上接受 WebSockets
/api/ws
As mentioned above by @Basj, make sure a2enmod proxy and ws_tunnel are enabled.
正如@Basj 上面提到的,确保启用了 a2enmod 代理和 ws_tunnel。
This is a screenshot of the Apache config file that solved my problem:
这是解决我的问题的 Apache 配置文件的屏幕截图:
The relevant part as text:
相关部分作为文本:
<VirtualHost *:80>
ServerName *******
ServerAlias *******
ProxyPass / http://localhost:3000/
ProxyPassReverse / http://localhost:3000/
<Location "/api/ws">
ProxyPass "ws://localhost:3000/api/ws"
</Location>
</VirtualHost>
Hope that helps.
希望有帮助。
回答by Ortwin Angermeier
Did the following for a spring application running static, rest and websocket content.
对运行静态、休息和 websocket 内容的 spring 应用程序执行以下操作。
The Apache is used as Proxy and SSL Endpoint for the following URIs:
Apache 用作以下 URI 的代理和 SSL 端点:
- /app → static content
- /api → REST API
- /api/ws → websocket
- /app → 静态内容
- /api → REST API
- /api/ws → websocket
Apache configuration
阿帕奇配置
<VirtualHost *:80>
ServerName xxx.xxx.xxx
ProxyRequests Off
ProxyVia Off
ProxyPreserveHost On
<Proxy *>
Require all granted
</Proxy>
RewriteEngine On
# websocket
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule ^/api/ws/(.*) ws://localhost:8080/api/ws/ [P,L]
# rest
ProxyPass /api http://localhost:8080/api
ProxyPassReverse /api http://localhost:8080/api
# static content
ProxyPass /app http://localhost:8080/app
ProxyPassReverse /app http://localhost:8080/app
</VirtualHost>
I use the same vHost config for the SSL configuration, no need to change anything proxy related.
我对 SSL 配置使用相同的 vHost 配置,无需更改任何与代理相关的内容。
Spring configuration
弹簧配置
server.use-forward-headers: true
回答by Arvind Madhukar
User this link for perfact solution for ws https://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html
使用此链接获取 ws https://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html 的完美解决方案
You have to just do below step..
你只需要做下面的步骤..
Go to /etc/apache2/mods-available
去 /etc/apache2/mods-available
Step...1
第1步
Enable mode proxy_wstunnel.loadby using below command
mode proxy_wstunnel.load使用以下命令启用
$a2enmod proxy_wstunnel.load
Step...2
第2步
Go to /etc/apache2/sites-available
去 /etc/apache2/sites-available
and add below line in your .conf file inside virtual host
并在虚拟主机内的 .conf 文件中添加以下行
ProxyPass "/ws2/" "ws://localhost:8080/"
ProxyPass "/wss2/" "wss://localhost:8080/"
Note : 8080 mean your that your tomcat running port because we want to connect wswhere our War file putted in tomcat and tomcat serve apache for ws.
thank you
注意:8080 表示您的 tomcat 运行端口,因为我们想连接ws我们的 War 文件放在 tomcat 和 tomcat 为 apache 服务的位置ws。谢谢你
My Configuration
我的配置
ws://localhost/ws2/ALLCAD-Unifiedcommunication-1.0/chatserver?userid=4 =Connected
回答by sNICkerssss
For "polling" transport.
用于“轮询”传输。
Apache side:
阿帕奇方面:
<VirtualHost *:80>
ServerName mysite.com
DocumentRoot /my/path
ProxyRequests Off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPass /my-connect-3001 http://127.0.0.1:3001/socket.io
ProxyPassReverse /my-connect-3001 http://127.0.0.1:3001/socket.io
</VirtualHost>
Client side:
客户端:
var my_socket = new io.Manager(null, {
host: 'mysite.com',
path: '/my-connect-3001'
transports: ['polling'],
}).socket('/');


