我在Ubuntu 14.04 LTS上运行Apache 2.4.7作为反向代理。 这个Apache服务器充当许多不同后端应用程序的入口点,这些应用程序可以通过<Location>块中的不同mod_proxyconfiguration来访问
我需要提供对使用WebSockets的应用程序的反向代理访问。 该应用程序是一个Java Spring应用程序,通过HTTP提供HTML和其他静态文件,然后在加载页面后使用WebSocket作为dynamic数据。
我已经使用以下configuration在Nginx后面运行应用程序:
location /newapp/ { proxy_pass http://newapp.example.com:8080/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; }
不幸的是,由于需要一个在Nginx上不可用的Apacheauthentication模块,我不能在生产中使用它。
我想要做的,在伪Apache的configuration是:
<Location /newapp/> if not WebSockets: ProxyPass http://newapp.example.com:8080/ ProxyPassReverse / else ProxyPass ws://newapp.example.com:8080/ ProxyPassReverse / </Location>
Apache的mod_proxy_wstunnel模块让我觉得这应该是可能的。 WebSocket可以通过URL /api/socket/... ,所以我尝试使用单独的<Location>块来分隔两种types的ProxyPass :
<Location /newapp/> ProxyPass http://newapp.example.com:8080/ disablereuse=on ProxyPassReverse / ProxyPassReverseCookieDomain newapp.example.com apps.example.com ProxyPassReverseCookiePath http://newapp.example.com:8080/ /newapp/ </Location> <Location /newapp/api/socket/> ProxyPass ws://newapp.example.com:8080/api/socket/ ProxyPassReverse / </Location>
这最初起作用 – 浏览器请求http://apps.example.com/newapp/ ,通过HTTP加载页面,加载静态资源,JavaScript代码连接到websocket,一切都很棒。
但是,当一个新的请求通过HTTP进行 – 比如GET /newapp/static/someimage.png ,出现了一些问题。 这个请求不匹配WebSocket Location,所以我希望它代理GET /static/someimage.png到http://newapp.example.com:8080/ 。
相反,应用程序服务器收到一个GET /newapp/static/someimage.png的请求,并返回一个404,因为这不是它意识到的URL。 这会中断应用程序,因为应该运行的HTTP请求会失败。
笔记:
GET /newapp/api/ajax/someapicall也会通过不正确的代理。 <Location /newapp/api/socket/>部分会导致两件事 – WebSocket无法连接,并且HTTP请求继续工作。 我认为正在发生:
我认为mod_proxy_wstunnel一旦被匹配/newapp/api/socket/的第一个请求激活,就会接pipe来自客户端的所有进一步入站请求,无论它们是否与Location匹配。 我testing了这个通过添加一个RequestHeader set Test "some_identifying_value"指令到每个Location – 静态文件的HTTP请求&为/api/socket/info有他们的Test头,但不正确的代理HTTP请求没有Test头文件,这表明他们正在被直接传递而没有被Apache指令处理。
最终,我的问题是这样的:是否有可能configuration任何版本的Apache(我很高兴升级!)反向代理基于WebSocket的应用程序,使得HTTP请求也正确地反向代理后,WebSocket有连接的? 如果是的话,这是如何configuration的?
我使用Apache 2.4作为我的春季启动应用程序的代理,这个应用程序提供了一些其他API调用,websockets(sockjs)和一些静态页面。 我有一些问题让websocket工作,秘密是添加你看到下面的重写规则 ,现在它适用于我,我的apache虚拟主机configuration看起来像这样:
<VirtualHost *:443> SSLEngine on SSLCertificateFile /etc/httpd/ssl/my.crt SSLCertificateKeyFile /etc/httpd/ssl/my.key SSLCertificateChainFile /etc/httpd/ssl/intermediate.crt ProxyPreserveHost On ProxyPass / http://127.0.0.1:8080/ ProxyPassReverse / http://127.0.0.1:8080/ ProxyRequests Off RewriteEngine on RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC] RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC] RewriteRule .* ws://localhost:6868%{REQUEST_URI} [P] ServerName my.dnsname.com </VirtualHost>
安德斯的答案让我有95%的方式。
基本情况:
newapp.example.com上有一个服务器 /api/socket/ http://apps.example.com/newapp/ 这是如何在<Location>块中为上述场景configurationWebSockets和HTTP反向代理:
<Location /newapp/> ProxyPass http://newapp.example.com:8080/ ProxyPassReverse / RewriteEngine on RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC] RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC] RewriteRule /api/(.*) ws://newapp.example.com:8080/api/$1 [P] </Location>
最后的重写规则是至关重要的 – 如果没有它,我们会将request /newapp/api/socket传递给WebSocket服务器 – 拒绝它。
正则expression式parsing了api之后的所有东西 – 可能有更好的方法来捕获这个块,但这个工作。 然后我们必须记住readd /api/到最后的redirectURL。
最重要的是,HTTP请求在WebSocket连接build立后继续工作!