我有以下 VirtualHost 配置:
<VirtualHost *:80>
DocumentRoot /srv/emptywebroot
<Directory /srv/emptywebroot>
Require all denied
</Directory>
# Dashboard proxy
RewriteEngine on
LogLevel alert rewrite:trace6
RewriteCond %{HTTP:Upgrade} =websocket
RewriteRule /dashboard/(.*) ws://dashboard:3838/dashboard/$1 [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket
RewriteRule /dashboard/(.*) http://dashboard:3838/dashboard/$1 [P,L]
ProxyPreserveHost on
ProxyPassReverse /dashboard http://dashboard:3838/dashboard
</VirtualHost>
当我访问时,http://myurl/dashboard
我从仪表板后端收到 404。
当我检查重写日志时,我得到:
[Wed Mar 21 14:04:08.051070 2018] [rewrite:trace2] [pid 1548:tid 140453800191744] mod_rewrite.c(476): [client 10.174.120.65:59506] 10.174.120.65 - - [idisrv.sivsa.com/sid#7fbdfdd1ed20][rid#7fbdf018f0a0/initial] init rewrite engine with requested uri /dashboard/
[Wed Mar 21 14:04:08.051114 2018] [rewrite:trace1] [pid 1548:tid 140453800191744] mod_rewrite.c(476): [client 10.174.120.65:59506] 10.174.120.65 - - [idisrv.sivsa.com/sid#7fbdfdd1ed20][rid#7fbdf018f0a0/initial] pass through /dashboard/
[Wed Mar 21 14:04:08.051176 2018] [rewrite:trace3] [pid 1548:tid 140453800191744] mod_rewrite.c(476): [client 10.174.120.65:59506] 10.174.120.65 - - [idisrv.sivsa.com/sid#7fbdfdd1ed20][rid#7fbdf018f0a0/initial] [perdir /dashboard/] add path info postfix: /srv/emptywebroot/dashboard -> /srv/emptywebroot/dashboard/
[Wed Mar 21 14:04:08.051186 2018] [rewrite:trace3] [pid 1548:tid 140453800191744] mod_rewrite.c(476): [client 10.174.120.65:59506] 10.174.120.65 - - [idisrv.sivsa.com/sid#7fbdfdd1ed20][rid#7fbdf018f0a0/initial] [perdir /dashboard/] applying pattern '(.*)' to uri '/srv/emptywebroot/dashboard/'
[Wed Mar 21 14:04:08.051199 2018] [rewrite:trace4] [pid 1548:tid 140453800191744] mod_rewrite.c(476): [client 10.174.120.65:59506] 10.174.120.65 - - [idisrv.sivsa.com/sid#7fbdfdd1ed20][rid#7fbdf018f0a0/initial] [perdir /dashboard/] RewriteCond: input='' pattern='=websocket' => not-matched
[Wed Mar 21 14:04:08.051208 2018] [rewrite:trace3] [pid 1548:tid 140453800191744] mod_rewrite.c(476): [client 10.174.120.65:59506] 10.174.120.65 - - [idisrv.sivsa.com/sid#7fbdfdd1ed20][rid#7fbdf018f0a0/initial] [perdir /dashboard/] add path info postfix: /srv/emptywebroot/dashboard -> /srv/emptywebroot/dashboard/
[Wed Mar 21 14:04:08.051216 2018] [rewrite:trace3] [pid 1548:tid 140453800191744] mod_rewrite.c(476): [client 10.174.120.65:59506] 10.174.120.65 - - [idisrv.sivsa.com/sid#7fbdfdd1ed20][rid#7fbdf018f0a0/initial] [perdir /dashboard/] applying pattern '(.*)' to uri '/srv/emptywebroot/dashboard/'
[Wed Mar 21 14:04:08.051225 2018] [rewrite:trace4] [pid 1548:tid 140453800191744] mod_rewrite.c(476): [client 10.174.120.65:59506] 10.174.120.65 - - [idisrv.sivsa.com/sid#7fbdfdd1ed20][rid#7fbdf018f0a0/initial] [perdir /dashboard/] RewriteCond: input='' pattern='!=websocket' => matched
[Wed Mar 21 14:04:08.051234 2018] [rewrite:trace2] [pid 1548:tid 140453800191744] mod_rewrite.c(476): [client 10.174.120.65:59506] 10.174.120.65 - - [idisrv.sivsa.com/sid#7fbdfdd1ed20][rid#7fbdf018f0a0/initial] [perdir /dashboard/] rewrite '/srv/emptywebroot/dashboard/' -> 'http://dashboard:3838//srv/emptywebroot/dashboard/'
[Wed Mar 21 14:04:08.051243 2018] [rewrite:trace2] [pid 1548:tid 140453800191744] mod_rewrite.c(476): [client 10.174.120.65:59506] 10.174.120.65 - - [idisrv.sivsa.com/sid#7fbdfdd1ed20][rid#7fbdf018f0a0/initial] [perdir /dashboard/] escaped URI in per-dir context for proxy, http://dashboard:3838//srv/emptywebroot/dashboard/ -> http://dashboard:3838//srv/emptywebroot/dashboard/
[Wed Mar 21 14:04:08.051264 2018] [rewrite:trace2] [pid 1548:tid 140453800191744] mod_rewrite.c(476): [client 10.174.120.65:59506] 10.174.120.65 - - [idisrv.sivsa.com/sid#7fbdfdd1ed20][rid#7fbdf018f0a0/initial] [perdir /dashboard/] forcing proxy-throughput with http://dashboard:3838//srv/emptywebroot/dashboard/
[Wed Mar 21 14:04:08.051272 2018] [rewrite:trace1] [pid 1548:tid 140453800191744] mod_rewrite.c(476): [client 10.174.120.65:59506] 10.174.120.65 - - [idisrv.sivsa.com/sid#7fbdfdd1ed20][rid#7fbdf018f0a0/initial] [perdir /dashboard/] go-ahead with proxy request proxy:http://dashboard:3838//srv/emptywebroot/dashboard/ [OK]
因此/srv/emptywebroot
在将 URI 传递给代理之前会添加前缀。我希望不添加前缀。我尝试过RewriteBase /
其他一些方法,但我不明白这一点。
在这种情况下,如何避免将 DocumentRoot 作为 URI 的前缀?
编辑1:位于仪表盘:3838 的仪表盘后端不是由 apache 提供的,它是一个 shiny 服务器(https://shiny.rstudio.com/)。我在仪表盘的主机上运行了一个 tcpdump,发生的事情如上所示:DocumentRoot 被 apache 的代理虚拟主机作为前缀,因此后端被要求http://仪表板:3838//srv/emptywebroot/仪表板, 代替http://仪表板:3838/仪表板正如我所需要的。我希望这能澄清我的情况,因此重新表述问题:我如何指示 mod_rewrite 不解析本地路径(以 DocumentRoot 为前缀)?在我的情况下,这是一个 mod_rewrite 代理(检查重写规则中的 [P],因此以本地路径为前缀不是我想要的行为。
答案1
根据重写日志,你的规则集的这些行已被命中
RewriteCond %{HTTP:Upgrade} !=websocket
RewriteRule /dashboard/(.*) http://dashboard:3838/dashboard/$1 [P,L]
由于RewriteRule
有[L]
标志,因此将不再检查下一行
现在,此请求将进入下一轮重写,<VirtualHost dashboard:3838>
您可以在那里查找为什么您的 URI/dashboard/
会导致 HTTP 错误 404。
- 该目录存在吗?
- 是否有任何 RewriteRule 可以解决该问题?
答案2
我发现强制重写规则与 REQUEST_URI 匹配(通过在 REQUEST_URI 之前添加重写条件)可以解决该问题,因此以下方法对我有用:
<VirtualHost *:80>
DocumentRoot /srv/emptywebroot
<Directory /srv/emptywebroot>
Require all denied
</Directory>
# Dashboard proxy
RewriteEngine on
LogLevel alert rewrite:trace6
RewriteCond %{HTTP:Upgrade} =websocket
RewriteCond %{REQUEST_URI} ^/dashboard
RewriteRule /dashboard/(.*) ws://dashboard:3838/dashboard/$1 [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket
RewriteCond %{REQUEST_URI} ^/dashboard
RewriteRule /dashboard/(.*) http://dashboard:3838/dashboard/$1 [P,L]
ProxyPreserveHost on
ProxyPassReverse /dashboard http://dashboard:3838/dashboard
</VirtualHost>
我找到了文档http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewriterule有点令人困惑,因为它指出“在 VirtualHost 上下文中,Pattern 最初将与 URL 中主机名和端口之后、查询字符串之前的部分进行匹配(例如“/app1/index.html”)。这是(% 解码的)URL 路径。”,但在我的例子中,它似乎与本地解析路径匹配。因此,添加 RewriteCond 来修改 RewriteRule 重写的内容(在我的例子中是 REQUEST_URI)似乎有效。