繁体   English   中英

WebSockets 和 Apache 代理:如何配置 mod_proxy_wstunnel?

[英]WebSockets and Apache proxy : how to configure mod_proxy_wstunnel?

我有 :

  1. Apache (v2.4) 在我的服务器的端口 80 上为www.domain1.com启用mod_proxymod_proxy_wstunnel

  2. 同一服务器的 3001 端口上的node.js + socket.io

访问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>

它适用于所有内容,除了 websocket 部分: ws://...不会像代理那样传输。

当我访问www.domain2.com上的页面时,我有:

Impossible to connect ws://www.domain2.com/socket.io/?EIO=3&transport=websocket&sid=n30rqg9AEqZIk5c9AABN.

问题:如何让 Apache 也代理 WebSockets?

由于这个话题 ,我终于设法做到了。

去做:

1)安装Apache 2.4(不适用于2.2),并执行:

a2enmod proxy
a2enmod proxy_http
a2enmod proxy_wstunnel

2)让nodejs在端口3001上运行

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/$1 [P,L]

  ProxyPass / http://localhost:3001/
  ProxyPassReverse / http://localhost:3001/
</VirtualHost>

注意:如果在使用websockets的同一服务器上有多个服务,则可能需要执行此操作以将它们分开。

您也可以按HTTP标头过滤,而不是按URL过滤。 此配置适用于任何使用websockets的Web应用程序,如果它们不使用socket.io:

<VirtualHost *:80>
  ServerName www.domain2.com

  RewriteEngine On
  RewriteCond %{HTTP:Upgrade} =websocket [NC]
  RewriteRule /(.*)           ws://localhost:3001/$1 [P,L]
  RewriteCond %{HTTP:Upgrade} !=websocket [NC]
  RewriteRule /(.*)           http://localhost:3001/$1 [P,L]

  ProxyPassReverse / http://localhost:3001/
</VirtualHost>

可能会有用。 只是所有查询都通过ws发送到节点

<VirtualHost *:80>
  ServerName www.domain2.com

  <Location "/">
    ProxyPass "ws://localhost:3001/"
  </Location>
</VirtualHost>

从Socket.IO 1.0(2014年5月)开始,所有连接都以HTTP轮询请求开始( 此处有更多信息)。 这意味着除了转发WebSocket流量之外,您还需要转发任何transport=polling HTTP请求。

下面的解决方案应该正确地重定向所有套接字流量,而不重定向任何其他流量。

  1. 启用以下Apache2 mods:

     sudo a2enmod proxy rewrite proxy_http proxy_wstunnel 
  2. 在* .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/$1 [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/$1 [P] # OPTIONAL: Route all HTTP traffic at /node to port 3001 ProxyRequests Off ProxyPass /node http://localhost:3001 ProxyPassReverse /node http://localhost:3001 </VirtualHost> 
  3. 我已经为路由/node流量添加了一个额外的部分,我觉得很方便,请参阅此处了解更多信息。

在这些答案的帮助下,我终于使用这个Apache2站点配置在使用Ubuntu Mate和Apache2的Raspberry Pi上运行Node-RED的反向代理:

<VirtualHost *:80>
    ServerName nodered.domain.com
    RewriteEngine On
    RewriteCond %{HTTP:Upgrade} =websocket [NC]
    RewriteRule /(.*)           ws://localhost:1880/$1 [P,L]
    RewriteCond %{HTTP:Upgrade} !=websocket [NC]
    RewriteRule /(.*)           http://localhost:1880/$1 [P,L]
</VirtualHost>

我还必须启用这样的模块:

sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_wstunnel

对我来说,它只能在httpd.conf中添加一行 ,如下所示(粗线)。


<VirtualHost *:80>
    ServerName: xxxxx

    #ProxyPassReverse is not needed
    ProxyPass /log4j ws://localhost:4711/logs
<VirtualHost *:80>

在CentOS上,Apache版本是2.4.6。

我的设置:

  • Apache 2.4.10(运行Debian)
  • Node.js(版本4.1.1)在端口3000上运行的应用程序,它接受路径/api/ws WebSockets

如上所述@Basj,请确保启用了a2enmod代理和ws_tunnel。

这是解决我的问题的Apache配置文件的屏幕截图:

Apache配置

相关部分为文字:

<VirtualHost *:80>
  ServerName *******
  ServerAlias *******
  ProxyPass / http://localhost:3000/
  ProxyPassReverse / http://localhost:3000/

  <Location "/api/ws">
      ProxyPass "ws://localhost:3000/api/ws"
  </Location>
</VirtualHost>

希望有所帮助。

对弹簧应用程序执行以下操作是否运行静态,休息和websocket内容。

Apache用作以下URI的代理和SSL端点:

  • / app→静态内容
  • / api→REST API
  • / api / ws→websocket

Apache配置

<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/$1   [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>

我使用相同的vHost配置进行SSL配置,无需更改任何与代理相关的内容。

弹簧配置

server.use-forward-headers: true

除了主要答案:如果在使用websockets的同一服务器上有多个服务,您可能希望通过使用自定义路径 (*)将它们分开:

节点服务器:

var io = require('socket.io')({ path: '/ws_website1'}).listen(server);

客户端HTML:

<script src="/ws_website1/socket.io.js"></script>
...
<script>
var socket = io('', { path: '/ws_website1' });
...

Apache配置:

RewriteEngine On

RewriteRule ^/website1(.*)$ http://localhost:3001$1 [P,L]

RewriteCond %{REQUEST_URI}  ^/ws_website1 [NC]
RewriteCond %{QUERY_STRING} transport=websocket [NC]
RewriteRule ^(.*)$ ws://localhost:3001$1 [P,L]

RewriteCond %{REQUEST_URI}  ^/ws_website1 [NC]
RewriteRule ^(.*)$ http://localhost:3001$1 [P,L]

(*)注意:使用默认的RewriteCond %{REQUEST_URI} ^/socket.io不会特定于网站,并且websockets请求将在不同的网站之间混淆!

对于 Windows 上的相同问题,只需从 http.conf 中取消注释以下行:

在此处输入图片说明

然后将以下行添加到您的 apache 配置中:

    LoadModule proxy_module modules/mod_proxy_wstunnel.so

用于“投票”运输。

Apache方面:

<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>

客户端:

var my_socket = new io.Manager(null, {
    host: 'mysite.com',
    path: '/my-connect-3001'
    transports: ['polling'],
}).socket('/');

使用此链接获取ws https://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html的 perfact解决方案

你必须在下面做一步..

转到/etc/apache2/mods-available

步骤1

使用以下命令启用mode proxy_wstunnel.load

$a2enmod proxy_wstunnel.load

第2步

转到/etc/apache2/sites-available

并在虚拟主机内的.conf文件中添加以下行

ProxyPass "/ws2/"  "ws://localhost:8080/"

ProxyPass "/wss2/" "wss://localhost:8080/"

注意:8080意味着你的tomcat运行端口是因为我们要连接ws ,我们的war文件放在tomcat中,而tomcat为ws提供apache。 谢谢

我的配置

ws://localhost/ws2/ALLCAD-Unifiedcommunication-1.0/chatserver?userid=4 =Connected

去做:

  1. 安装Apache 2.4(不适用于2.2), a2enmod proxya2enmod proxy_wstunnel.load

  2. 在Apache配置中执行此操作
    只需在文件中添加两行,其中8080​​是您的tomcat运行端口

     <VirtualHost *:80> ProxyPass "/ws2/" "ws://localhost:8080/" ProxyPass "/wss2/" "wss://localhost:8080/" </VirtualHost *:80> 

暂无
暂无

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

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