当使用mod_rewrite' s RewriteRule
执行重写时,将根据是否根目录来评估替换,并猜测它是URL还是文件系统路径。替换存在于文件系统上。这是the documentation的相关部分:
URL路径
请注意,mod_rewrite尝试通过检查文件系统根目录中是否存在路径的第一个段来猜测您是否指定了文件系统路径或URL路径。例如,如果您指定 Substitution 字符串
/www/file.html
,那么这将被视为URL路径,除非存在名为www
的目录在根目录或文件系统中(或者,如果在.htaccess
文件中使用相对于文档根目录的重写),在这种情况下,它将被视为文件系统路径。
所以我的问题是,如何重写URI,文件系统中存在根目录 ,但我希望将其视为URL?
除了指定完整的URL之外,还有其他方法吗?另外根据文档:
绝对网址
如果指定了绝对URL,mod_rewrite将检查主机名是否与当前主机匹配。如果是,则删除方案和主机名,并将生成的路径视为URL路径。否则,将对给定的URL执行外部重定向。
所以我可以像这样绕过它:
RewriteRule ^/example.html$ %{REQUEST_SCHEME}://%{HTTP_HOST}/var/example.html
这对于代码的可读性并不理想。我真的希望能够做到:
RewriteRule ^/example.html$ /var/example.html
当/var
存在时,不将其评估为文件系统路径。似乎并不是强迫它的旗帜。还存在以后创建匹配路径和破坏规则的风险,我希望避免这种情况没有那么多冗长。
我也知道我可以通过将规则放在.htaccess
而不是Apache配置中来解决这个问题,因此搜索是从文档根目录进行的,如上面引用中所述,但那不是我正在寻找什么。
还有其他办法吗?
更新
感谢Dusan Bajic的回答,事实证明[PT]
标志可以在这里提供帮助,正如在句子中暗示我错过了文档中的第一个引用:
如果您希望将其他URL映射指令(例如Alias)应用于生成的URL路径,请使用[PT]标志,如下所述。
通过使用[PT]
标志(docs here),它将导致替换"被视为URI而不是[文件路径]",这听起来它应该回答这个问题,但不幸的是,使用[PT]
标志还有其他含义:
[L]
,因此不会再进行重写规则处理。所以我现在暂时没有接受这个问题,因为理想的解决方案不会出现上述问题。接受的答案将导致替换被视为URL路径,就像在文件系统中不存在替换的根目录一样,而不会以任何其他方式影响处理。
更新2
我意识到,当URL在文档根目录中时,另一个帮助解决此问题的方法是在替换开始时始终添加%{DOCUMENT_ROOT}
。所以它就像这样:
RewriteRule ^/example.html$ %{DOCUMENT_ROOT}/var/example.html
这也可以防止以后处理URL的规则工作,因此它与[PT]
选项类似,但不会导致URL映射再次运行。
答案 0 :(得分:4)
你忽略了引用段落的最后一句:
如果您希望应用其他URL映射指令(例如Alias) 在生成的URL路径中,使用[PT]标志,如下所述。
似乎它不适用于你的(非常明智的btw。)问题,但如果你进一步深入研究[PT]:
假设RewriteRule中的目标(或替换字符串) 默认情况下为文件路径。使用[PT]标志会导致它 被视为URI。
例如(如果您启用LogLevel debug rewrite:trace6
):
RewriteRule ^/boo$ /opt/mock.png
将记录:
[...] init rewrite engine with requested uri /boo
[...] applying pattern '^/boo$' to uri '/boo'
[...] rewrite '/boo' -> '/opt/mock.png'
[...] local path result: /opt/mock.png
[...] go-ahead with /opt/mock.png [OK]
但是
RewriteRule ^/boo$ /opt/mock.png [PT]
将记录:
[...] init rewrite engine with requested uri /boo
[...] applying pattern '^/boo$' to uri '/boo'
[...] rewrite '/boo' -> '/opt/mock.png'
[...] forcing '/opt/mock.png' to get passed through to next API URI-to-filename handler