Bri*_*ett 3 reverse-proxy mod-proxy apache-2.4 websocket
我在 Ubuntu 14.04 LTS 上运行 Apache 2.4.7 作为反向代理。这个 Apache 服务器充当许多不同后端应用程序的入口点,这些应用程序通过<Location>
块中不同的 mod_proxy 配置进行访问
我需要提供对使用 WebSocket 的应用程序的反向代理访问。该应用程序是一个 Java Spring 应用程序,它通过 HTTP 提供 HTML 和其他静态文件,然后在页面加载后使用 WebSocket 获取动态数据。
我已经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";
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,由于需要一个在 Nginx 上不可用的 Apache 身份验证模块,我无法在生产中使用它。
我想要做的是,在伪 Apache-config 中:
<Location /newapp/>
if not WebSockets:
ProxyPass http://newapp.example.com:8080/
ProxyPassReverse /
else
ProxyPass ws://newapp.example.com:8080/
ProxyPassReverse /
</Location>
Run Code Online (Sandbox Code Playgroud)
Apachemod_proxy_wstunnel
模块让我觉得这应该是可能的。WebSocket 是在 URL 上访问的/api/socket/...
,因此我尝试将ProxyPass
使用单独<Location>
块的两种类型分开:
<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>
Run Code Online (Sandbox Code Playgroud)
这最初有效 - 浏览器请求http://apps.example.com/newapp/,页面通过 HTTP 加载,静态资产被加载,JavaScript 代码连接到 websocket,一切都很棒。
但是,当通过 HTTP 发出新请求时 - 例如,对于GET /newapp/static/someimage.png
,就会出现问题。此请求与 WebSocket 位置不匹配,因此我希望它代理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/
,就会接管来自客户端的所有进一步入站请求,无论它们是否匹配Location
。我通过向RequestHeader set Test "some_identifying_value"
每个Location
文件添加一个指令来测试这一点- 静态文件的 HTTP 请求和 for在它们上面/api/socket/info
有Test
标头,但是错误代理的 HTTP 请求上没有Test
标头,这表明它们被直接传递而没有被由 Apache 指令处理。
最终,我的问题是:是否可以将任何版本的 Apache(我很高兴升级!)配置为反向代理基于 WebSocket 的应用程序,以便在 WebSocket 完成后,HTTP 请求也被正确反向代理连接的?如果是这样,这是如何配置的?
安德斯的回答让我成功了 95%。
基本场景:
newapp.example.com
/api/socket/
http://apps.example.com/newapp/
这是在一个<Location>
块中为上述场景配置 WebSockets 和 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>
Run Code Online (Sandbox Code Playgroud)
最终的重写规则至关重要 - 没有它,我们会将请求/newapp/api/socket
传递给 WebSocket 服务器 - 它会拒绝。
正则表达式正在解析之后的所有内容api
- 可能有更好的方法来捕获该块,但这有效。然后我们必须记住重新添加/api/
到最终重定向 URL。
最重要的是,HTTP 请求在 WebSocket 连接建立后继续工作!
归档时间: |
|
查看次数: |
11827 次 |
最近记录: |