在调试重写规则时,我注意到一些出乎意料的事情:事件的顺序似乎是Apache处理规则,然后追溯地应用前面的条件。这是设计的,还是我误解了什么?
这是我的.htaccess文件中的重写规则的简单示例。它实际上并没有做任何有用的事情-只是一个例子。
RewriteEngine on
Options FollowSymLinks
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . / [L]
这是结果跟踪(为便于阅读而大量编辑)
[...redacted...] init rewrite engine with requested uri /test.html
[...redacted...] pass through /test.html
[...redacted...] [perdir /var/www/html/] strip per-dir prefix: /var/www/html/test.html -> test.html
[...redacted...] [perdir /var/www/html/] applying pattern '.' to uri 'test.html'
[...redacted...] [perdir /var/www/html/] RewriteCond: input='/var/www/html/test.html' pattern='!-f' => not-matched
[...redacted...] [perdir /var/www/html/] pass through /var/www/html/test.html
请注意,在应用模式之后,将应用“ RewriteCond” 。最终结果是传递是正确的(因为该文件确实存在,实际上是存在的),因此这并不重要。我在文档中找不到关于此的任何内容。
事件的顺序似乎是Apache处理一条规则,然后追溯地应用前面的条件。这是设计的,还是我误解了什么?
是的,这就是它的工作原理。
RewriteRule必须先匹配。只有在这种情况下,才会评估RewriteCond-itions。如果这些都匹配,则执行重写。
在描述RewriteCond和-Rule语法的手册页上没有这么清楚地提及。https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html#rewritecond刚刚说,
然后,仅当URI的当前状态与它的模式都匹配并且满足这些条件时,才使用以下规则。
现在,您可能暗示了处理顺序(如果您按“逻辑”顺序从左到右阅读),但是它不是很明确。
但是https://httpd.apache.org/docs/2.4/rewrite/intro.html#regex说,
正则表达式的反向引用可用性
这里必须记住一件事:每当在Pattern或CondPattern之一中使用括号时,内部都会创建反向引用,该反向引用可与字符串$ N和%N一起使用(请参见下文)。这些可用于创建RewriteRule的Substitution参数或RewriteCond的TestString参数。RewriteRule模式中的捕获(违反直觉)可用于所有前面的RewriteCond指令,因为RewriteRule表达式是在各个条件之前求值的。
(最后由我突出显示。)
因此,在那个地方您发现了明确提到的这种行为。