如何配置Apache以正确转发Websockets?

问题描述:

我已经看过this question以及SO和其他相关网站上的其他人,但迄今为止所提出的解决方案都没有奏效。如何配置Apache以正确转发Websockets?

我在localhost:8080上运行tty.js,并验证当直接点击该端口时websockets正常工作。现在,我试图通过Apache反向代理连接到tty.js。该应用程序可以不使用Websockets,但我想了解为什么Websockets不起作用。

这是我的Apache配置,用于在localhost上进行测试,其中包含source的新版Apache版本。

Listen 9000 
# Load proxy modules 
LoadModule proxy_module "modules/mod_proxy.so" 
LoadModule proxy_http_module "modules/mod_proxy_http.so" 
LoadModule proxy_wstunnel_module "modules/mod_proxy_wstunnel.so" 

<VirtualHost *:9000> 
ServerName localhost 

ProxyPass /tty/socket.io/1/ ws://localhost:8080/socket.io/1/ 
ProxyPassReverse /tty/socket.io/1/ ws://localhost:8080/socket.io/1/ 
ProxyPass /tty/ http://localhost:8080/ 
ProxyPassReverse /tty/ http://localhost:8080/ 

</VirtualHost> 

当我连接到http://localhost:9000/tty/,我得到一个500错误。

在服务器端日志中,出现以下错误。

[Mon Jan 02 19:30:32.342551 2017] [proxy:warn] [pid 28226:tid 140098955872000] [client 127.0.0.1:38372] AH01144: No protocol handler was valid for the URL /tty/socket.io/1/. If you are using a DSO version of mod_proxy, make sure the proxy submodules are included in the configuration using LoadModule., referer: http://localhost:9000/tty/ 

什么是正确的配置Apache以使WebSockets的正常工作?

在调试器中运行Apache几个小时后,我发现Apache正在通过mod_proxy忠实地传递与给定路径相匹配的所有请求,包括以下内容。

http://localhost:9000/tty/socket.io/1/ 

事实证明,这个请求转到脱离与Upgrade: Websocket头的实际请求之前,并且它是一个正常AJAX请求

当这个请求被传递到mod_proxy_wstunnel,模块通告的WebSocket的头部丢失,并拒绝处理它,造成权利要求的Apache是​​No protocol handler was valid日志消息,并返回状态码500

修复的方法是扩展ProxyPath指令的路径,以便它只覆盖实际的WebSocket请求,而不会丢弃Ajax请求。

ProxyPass /tty/socket.io/1/websocket/ ws://localhost:8080/socket.io/1/websocket/ 
ProxyPassReverse /tty/socket.io/1/websocket/ ws://localhost:8080/socket.io/1/websocket/