我一直在尝试将带有 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(&|$)/ & ..."
等等,其中backend
和frontend
分别是后端和前端服务器 URL 的正则表达式。对于Content-Location
和URI
标头也是如此。在 Apache 2.2 中,表达式的等价形式是使用来RewriteRule
设置环境变量,env
并向Header
指令添加子句。