I am trying to set up a reverse proxy with Apache 2.4.
It looks like I cannot use the horrible mod_proxy
directly, as it does not support websockets (unless manually configured for every single URL), so I have to use the horrible horrible mod_rewrite
instead.
My configuration looks as follows so far:
<VirtualHost *:80>
ServerName collabora.example.com
RewriteEngine on
RewriteCond %{HTTP:Upgrade} =websocket
RewriteRule ^(/.*)?$ wss://collabora-backend$1 [P]
RewriteCond %{HTTP:Upgrade} !=websocket
RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/?
RewriteRule ^(/.*)?$ https://collabora-backend$1 [P]
</VirtualHost>
One application that I’m trying to run (the horrible³ Collabora Online in combination with NextCloud) will try to open WebSockets to URLs like this: ws://collabora.example.com/lool/https%253A%252F%252Fcloud.example.com%252Fapps%252Frichdocuments%252Fwopi%252Ffiles%252F51040%3Faccess_token%3DABCDEF%26permission%3Dedit/ws
. Unfortunately, with the configuration above, these URLs will arrive at the backend with all the %25
parts decoded to %
(and others as well): ws://collabora.example.com/lool/https%3A%2F%2Fcloud.example.com%2Fapps%2Frichdocuments%2Fwopi%2Ffiles%2F51040?access_token=ABCDEF&permission=edit/ws
.
Collabora will report error messages like this:
wsd-00026-0195 0:01:27.448231 [ client_ws_0003 ] ERR Unknown resource: /lool//ws/lool/https%253A%252F%252Fowncloud.mydomain.fr%252Findex.php%252Fapps%252Frichdocuments%252Fwopi%252Ffiles%252F5%3Faccess_token=R...c&permission=edit/ws| LOOLWSD.cpp:1154
and the WebSocket connections will fail with a 400 Bad Request
error in the browser.
Setting AllowEncodedSlashes
to On
or NoDecode
doesn’t change this. (As far as I understand, this only affects the value of PATH_INFO
.)
Reading through the RewriteRule
flags, the [B]
flag seems to talk about something related to my problem. There it says “mod_rewrite has to unescape URLs before mapping them” (I assume the sole reason for that being to maximise annoyance), so the [B]
flag will re-escape them again after the mapping. This of course doesn’t work in this case and will escape all the slashes, even the ones that were not escaped before: "ws://collabora.example.com%2Flool%2Fhttps%253A%252F%252Fcloud.example.com%252Fapps%252Frichdocuments%252Fwopi%252Ffiles%252F51040%3Faccess_token%3DABCDEF%26permission%3Dedit%2Fws"
Is there a way to fix this issue or is this the point where I finally have to get rid of Apache for good?
Based on covener’s answer, I have now come up with the following configuration that works:
I adjusted covener’s answer to support all kinds of HTTP requests, and I had to add the
NE
flag (otherwise the request URI would be escaped once more).