由于 Apache mod_rewrite 代理未转义 %2F 斜杠,Collabora“未知资源”
Collabora “Unknown resource” because of Apache mod_rewrite proxy unescaping %2F slashes
我正在尝试使用 Apache 2.4 设置反向代理。
看来我不能直接使用可怕的mod_proxy
,因为它不支持websockets(除非为每个URL手动配置),所以我必须使用可怕的可怕mod_rewrite
代替。
到目前为止,我的配置如下所示:
<VirtualHost *:80>
ServerName collabora.example.com
RewriteEngine on
RewriteCond %{HTTP:Upgrade} =websocket
RewriteRule ^(/.*)?$ wss://collabora-backend [P]
RewriteCond %{HTTP:Upgrade} !=websocket
RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/?
RewriteRule ^(/.*)?$ https://collabora-backend [P]
</VirtualHost>
我正在尝试 运行(可怕的³ Collabora Online in combination with NextCloud)的一个应用程序将尝试向 URL 开放 WebSocket,如下所示:ws://collabora.example.com/lool/https%253A%252F%252Fcloud.example.com%252Fapps%252Frichdocuments%252Fwopi%252Ffiles%252F51040%3Faccess_token%3DABCDEF%26permission%3Dedit/ws
。不幸的是,使用上面的配置,这些 URL 将到达后端,所有 %25
部分都解码为 %
(以及其他部分):ws://collabora.example.com/lool/https%3A%2F%2Fcloud.example.com%2Fapps%2Frichdocuments%2Fwopi%2Ffiles%2F51040?access_token=ABCDEF&permission=edit/ws
.
Collabora 将报告如下错误消息:
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
并且 WebSocket 连接将失败并在浏览器中出现 400 Bad Request
错误。
将 AllowEncodedSlashes
设置为 On
或 NoDecode
不会改变这一点。 (据我了解,这只会影响 PATH_INFO
的值。)
通读RewriteRule
flags,[B]
flag好像说的和我的问题有关。那里写着“mod_rewrite has to unescape URLs before mapping them”(我假设这样做的唯一原因是为了最大限度地增加烦恼),所以 [B]
标志将再次对它们进行转义映射后。这在这种情况下当然不起作用,并且会转义所有斜线,甚至是之前没有转义的斜线:"ws://collabora.example.com%2Flool%2Fhttps%253A%252F%252Fcloud.example.com%252Fapps%252Frichdocuments%252Fwopi%252Ffiles%252F51040%3Faccess_token%3DABCDEF%26permission%3Dedit%2Fws"
有没有办法解决这个问题,或者这是我最终必须永远摆脱 Apache 的地步吗?
这方面的一个技巧是使用 %{THE_REQUEST} 的捕获而不是反向引用,因为它将使用请求的原始编码,例如:
<VirtualHost *:80>
ServerName collabora.example.com
RewriteEngine on
RewriteCond %{HTTP:Upgrade} =websocket
RewriteCond %{THE_REQUEST} "^GET /(.*) HTTP/1.?$"
RewriteRule ^(/.*)?$ wss://collabora-backend/%1 [P]
RewriteCond %{HTTP:Upgrade} !=websocket
RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/?
RewriteRule ^(/.*)?$ https://collabora-backend [P]
</VirtualHost>
我只添加了带捕获的新条件并将 $1 更改为 %1。我只是进行了桌面检查,但我怀疑它让你通过一些小的调整就解决了编码问题。
根据 covener 的回答,我现在想出了以下可行的配置:
<VirtualHost *:80>
ServerName collabora.example.com
RewriteEngine on
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteCond %{THE_REQUEST} "^[a-zA-Z]+ /(.*) HTTP/\d+(\.\d+)?$"
RewriteRule .? wss://collabora-backend/%1 [P,NE]
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/?
RewriteCond %{THE_REQUEST} "^[a-zA-Z]+ /(.*) HTTP/\d+(\.\d+)?$"
RewriteRule .? https://collabora-backend/%1 [P,NE]
</VirtualHost>
我调整了 covener 的答案以支持所有类型的 HTTP 请求,我不得不添加 NE
标志(否则请求 URI 将再次被转义)。
Collabora 更新了文档,我 运行 在同一期。
所以有一个更好的解决方案(在 https://www.collaboraoffice.com/code/ 找到)
AllowEncodedSlashes NoDecode
ProxyPassMatch "/lool/(.*)/ws$" wss://127.0.0.1:9980/lool//ws nocanon
我正在尝试使用 Apache 2.4 设置反向代理。
看来我不能直接使用可怕的mod_proxy
,因为它不支持websockets(除非为每个URL手动配置),所以我必须使用可怕的可怕mod_rewrite
代替。
到目前为止,我的配置如下所示:
<VirtualHost *:80>
ServerName collabora.example.com
RewriteEngine on
RewriteCond %{HTTP:Upgrade} =websocket
RewriteRule ^(/.*)?$ wss://collabora-backend [P]
RewriteCond %{HTTP:Upgrade} !=websocket
RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/?
RewriteRule ^(/.*)?$ https://collabora-backend [P]
</VirtualHost>
我正在尝试 运行(可怕的³ Collabora Online in combination with NextCloud)的一个应用程序将尝试向 URL 开放 WebSocket,如下所示:ws://collabora.example.com/lool/https%253A%252F%252Fcloud.example.com%252Fapps%252Frichdocuments%252Fwopi%252Ffiles%252F51040%3Faccess_token%3DABCDEF%26permission%3Dedit/ws
。不幸的是,使用上面的配置,这些 URL 将到达后端,所有 %25
部分都解码为 %
(以及其他部分):ws://collabora.example.com/lool/https%3A%2F%2Fcloud.example.com%2Fapps%2Frichdocuments%2Fwopi%2Ffiles%2F51040?access_token=ABCDEF&permission=edit/ws
.
Collabora 将报告如下错误消息:
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
并且 WebSocket 连接将失败并在浏览器中出现 400 Bad Request
错误。
将 AllowEncodedSlashes
设置为 On
或 NoDecode
不会改变这一点。 (据我了解,这只会影响 PATH_INFO
的值。)
通读RewriteRule
flags,[B]
flag好像说的和我的问题有关。那里写着“mod_rewrite has to unescape URLs before mapping them”(我假设这样做的唯一原因是为了最大限度地增加烦恼),所以 [B]
标志将再次对它们进行转义映射后。这在这种情况下当然不起作用,并且会转义所有斜线,甚至是之前没有转义的斜线:"ws://collabora.example.com%2Flool%2Fhttps%253A%252F%252Fcloud.example.com%252Fapps%252Frichdocuments%252Fwopi%252Ffiles%252F51040%3Faccess_token%3DABCDEF%26permission%3Dedit%2Fws"
有没有办法解决这个问题,或者这是我最终必须永远摆脱 Apache 的地步吗?
这方面的一个技巧是使用 %{THE_REQUEST} 的捕获而不是反向引用,因为它将使用请求的原始编码,例如:
<VirtualHost *:80>
ServerName collabora.example.com
RewriteEngine on
RewriteCond %{HTTP:Upgrade} =websocket
RewriteCond %{THE_REQUEST} "^GET /(.*) HTTP/1.?$"
RewriteRule ^(/.*)?$ wss://collabora-backend/%1 [P]
RewriteCond %{HTTP:Upgrade} !=websocket
RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/?
RewriteRule ^(/.*)?$ https://collabora-backend [P]
</VirtualHost>
我只添加了带捕获的新条件并将 $1 更改为 %1。我只是进行了桌面检查,但我怀疑它让你通过一些小的调整就解决了编码问题。
根据 covener 的回答,我现在想出了以下可行的配置:
<VirtualHost *:80>
ServerName collabora.example.com
RewriteEngine on
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteCond %{THE_REQUEST} "^[a-zA-Z]+ /(.*) HTTP/\d+(\.\d+)?$"
RewriteRule .? wss://collabora-backend/%1 [P,NE]
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteCond %{REQUEST_URI} !^/.well-known/acme-challenge/?
RewriteCond %{THE_REQUEST} "^[a-zA-Z]+ /(.*) HTTP/\d+(\.\d+)?$"
RewriteRule .? https://collabora-backend/%1 [P,NE]
</VirtualHost>
我调整了 covener 的答案以支持所有类型的 HTTP 请求,我不得不添加 NE
标志(否则请求 URI 将再次被转义)。
Collabora 更新了文档,我 运行 在同一期。
所以有一个更好的解决方案(在 https://www.collaboraoffice.com/code/ 找到)
AllowEncodedSlashes NoDecode
ProxyPassMatch "/lool/(.*)/ws$" wss://127.0.0.1:9980/lool//ws nocanon