2

I have been trying for the longest time to proxy a websocket with it's sid variable to the localhost service, that is serving it. I have looked far and beyond for a solution (including a lot of the questions here), but most of them suggest to use a VirtualHost, which I cannot do, since I do not want a subdomain and the virtualhost to my main domain already has a proxypass.

I am either forced to do it under a directive, as suggested on here, which returned me no results whatsoever, or edit the websocket itself, which I cannot do either, due to the app that I am running being closed source.

I have tried with the following:

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"

but it was not providing any working result. I have tried with different regex expressions as well, specifying the full path and even specifying the current websocket's sid, but nothing has worked. I always receive a 400 Bad request error in response and nothing related in the Apache2 logs.

I would appreciate any assistance.

smsimeon
  • 21
  • 1

1 Answers1

1

The ProxyPassMatch directive isn't matching because it only matches against the URL path, not the appended query string too, as you're trying to do.

To match the query string and do the proxying, you can use mod_rewrite, for example:

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]

Or something like that. See the mod_rewrite docs for details, in particular the RewriteRule P flag. Using multiple conditions on QUERY_STRING instead of one allows the parameters to match in any order.

That only does the equivalent of the ProxyPass directive. If you need ProxyPassReverse too, in Apache 2.4 you can add Header directives with expressions:

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

and so on, where backend and frontend are regexes for the URLs of the back and front end servers, respectively. And similarly for the Content-Location and URI headers. In Apache 2.2 the equivalent of the expression is to use the RewriteRule to set an environment variable, and add an env clause to the Header directive.

See also Configuring Apache2 to proxy WebSocket?.

Andrew Schulman
  • 8,561
  • 21
  • 31
  • 47
  • I ended up removing the service from the current one onto a different one due to the lack of resources on the current one, so I don't need a solution now, but it is something probably worth addressing. I couldn't have another RewriteRule, because I already had one in the same VirtualHost, so what you proposed couldn't have helped me. Thanks anyway. – smsimeon Feb 19 '18 at 12:39