我在端口 80 上有 Apache httpd,在端口 3000 上有 Morbo httpd 服务器,提供 perl Mojolicious 代码。Morbo 只能从本地主机使用。
现在我想设置带有代理的虚拟主机,以便静态文件由 Apache 提供,动态内容由 Morbo 提供。
这是我的虚拟主机配置:
<VirtualHost *:80>
ServerName mojo.myhost.com
DocumentRoot /opt/mojo/public
RewriteEngine on
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteRule ^(.*) http://localhost:3000$1 [NS,P,L]
ProxyPassReverse / http://mojo.myhost.com
</VirtualHost>
问题是,当我尝试访问http://mojo.myhost.com/
Apache 时,子请求由 Apache 发出,而发送到 Morbo 的请求是 http://localhost:3000/error/noindex.html
而不是http://localhost:3000/
。
以下是 mod-rewrite 日志的一部分:
[rid#2b20905c58e0/initial] (2) init rewrite engine with requested uri /
[rid#2b20905c58e0/initial] (3) applying pattern '^(.*)' to uri '/'
[rid#2b20905c58e0/initial] (4) RewriteCond: input='/opt/mojo/public/' pattern='!-f' => matched
[rid#2b20905c58e0/initial] (4) RewriteCond: input='/opt/mojo/public/' pattern='!-d' => not-matched
[rid#2b20905c58e0/initial] (1) pass through /
[rid#2b20905cb910/subreq] (2) init rewrite engine with requested uri /index.php
[rid#2b20905cb910/subreq] (1) pass through /index.php
[rid#2b20905cd920/subreq] (2) init rewrite engine with requested uri /index.html
[rid#2b20905cd920/subreq] (1) pass through /index.html
[rid#2b20905cb910/subreq] (2) init rewrite engine with requested uri /index.html.var
[rid#2b20905cb910/subreq] (1) pass through /index.html.var
[rid#2b20905cd920/subreq] (2) init rewrite engine with requested uri /index.htm
[rid#2b20905cd920/subreq] (1) pass through /index.htm
[rid#2b20905caf40/initial/redir#1] (2) init rewrite engine with requested uri /error/noindex.html
[rid#2b20905caf40/initial/redir#1] (3) applying pattern '^(.*)' to uri '/error/noindex.html'
[rid#2b20905caf40/initial/redir#1] (4) RewriteCond: input='/opt/mojo/public/error/noindex.html' pattern='!-f' => matched
[rid#2b20905caf40/initial/redir#1] (4) RewriteCond: input='/opt/mojo/public/error/noindex.html' pattern='!-d' => matched
[rid#2b20905caf40/initial/redir#1] (2) rewrite '/error/noindex.html' -> 'http://localhost:3000/error/noindex.html'
[rid#2b20905caf40/initial/redir#1] (2) forcing proxy-throughput with http://localhost:3000/error/noindex.html
[rid#2b20905caf40/initial/redir#1] (1) go-ahead with proxy request proxy:http://localhost:3000/error/noindex.html [OK]
我添加了NS
标志,RewriteRule
但 subreq 仍然在将 URL 传递给 Morbo 之前对其进行了修改。我怎样才能让 Apache 将 / 而不是 /error/noindex.html 传递给 Morbo?
如果RewriteCond
从虚拟主机配置中删除两者,那么它可以工作,但静态文件也由 Morbo 提供服务(我不太喜欢)。
答案1
以下是具体发生的情况:
- 服务器收到请求
/
- 服务器检查
-f
条件,发现这/
不是一个文件,因此符合条件。 - 服务器检查
-d
条件,发现/
是一个目录,因此它不符合条件。 - 由于不符合第二个条件,服务器尝试将其作为本地文件/目录进行处理。以 结尾的资源
/
应该有一个索引文件;因此它会尝试查找列出的所有索引文件。 - 由于它找不到索引文件,
/error/noindex.html
因此它想向您显示。 - 现在我们回过头来检查重写条件,这一次我们同时匹配了两者——既没有文件也没有目录
/error/noindex.html
,所以这次发出了代理请求
解决方案:
添加仅匹配空的 RewriteRule /
,并让该规则执行重写。示例:
RewriteRule ^/$ http://localhost:3000 [NS,P,L]
ProxyPassReverse / http://mojo.myhost.com
这仅匹配 的请求/
。