通过 proxypass/proxypassmatch 代理 websocket 参数,无需 VirtualHost

通过 proxypass/proxypassmatch 代理 websocket 参数,无需 VirtualHost

我一直在尝试将带有 sid 变量的 websocket 代理到为其提供服务的 localhost 服务。我四处寻找解决方案(包括这里的许多问题),但大多数都建议使用 VirtualHost,但我做不到,因为我不想使用子域,而且我主域的虚拟主机已经有代理密码了。

我要么被迫按照这里的建议按照指令去做,但这并没有给我返回任何结果,要么编辑 websocket 本身,但由于我运行的应用程序是闭源的,所以我也无法做到这一点。

我已尝试以下操作:

ProxyPassMatch "^/?type=player&EIO=3&transport=websocket&sid=(.*)$" "ws://127.0.0.1:3000/socket.io/?type=player&EIO=3&transport=websocket&sid=$1"
ProxyPassReverse "^/?type=player&EIO=3&transport=websocket&sid=(.*)$" "wss://127.0.0.1:3000/socket.io/?type=player&EIO=3&transport=websocket&sid=$1"

但它没有提供任何有效的结果。我也尝试了不同的正则表达式,指定完整路径,甚至指定当前 websocket 的 sid,但都不起作用。我总是收到 400 Bad request 错误作为响应,而 Apache2 日志中没有任何相关内容。

我将非常感激您的帮助。

答案1

ProxyPassMatch 指令不匹配,因为它仅与 URL 路径匹配,而不是与附加的查询字符串匹配,正如您尝试做的那样。

要匹配查询字符串并执行代理,您可以使用 mod_rewrite,例如:

RewriteCond %{QUERY_STRING} (^|&)type=player(&|$)
RewriteCond %{QUERY_STRING} (^|&)EIO=3(&|$)
RewriteCond %{QUERY_STRING} (^|&)transport=websocket(&|$)
RewriteCond %{QUERY_STRING} (^|&)sid=
RewriteRule ^/(.*) ws://127.0.0.1:3000/socket.io/$1 [P,QSA]

或者类似的东西。请参阅mod_rewrite 文档有关详细信息,特别是RewriteRule P 标志。使用多个条件QUERY_STRING而不是一个条件允许参数按任何顺序匹配。

这只起到与ProxyPass指令相同的作用。如果您ProxyPassReverse也需要,在 Apache 2.4 中,您可以添加标头指令使用表达式:

Header edit Location backend frontend "expr=%{QUERY_STRING} =~ /(^|&)type=player(&|$)/ & ..."

等等,其中backendfrontend分别是后端和前端服务器 URL 的正则表达式。对于Content-LocationURI标头也是如此。在 Apache 2.2 中,表达式的等价形式是使用来RewriteRule设置环境变量,env并向Header指令添加子句。

也可以看看配置 Apache2 来代理 WebSocket?

相关内容