htaccess问题 - 奇怪的[OR]行为

时间:2015-12-01 16:18:45

标签: .htaccess

我注意到htaccess中的[OR]问题我不明白。我想要做的是将每个不存在的文件和每个.php文件(而不是/index.php)的文件重定向到/ 404 /。根据我的理解,下面两个块应该做同样的事情:

# .htaccess 1
RewriteEngine on

# cond 1
RewriteCond %{REQUEST_FILENAME} !-f [OR]
# cond 2
RewriteCond %{REQUEST_FILENAME} !index\.php$
# cond 3
RewriteCond %{REQUEST_URI} \.php$
# rule 1
RewriteRule [^\.]*\.[a-zA-Z0-9]+$ /404/ [L]

# rule 2
RewriteRule ^(([^/\.]+)/?)*?$ /index.php [L]

和此:

# .htaccess 2
RewriteEngine on

# cond 1
RewriteCond %{REQUEST_FILENAME} !-f
# rule 1
RewriteRule [^\.]*\.[a-zA-Z0-9]+$ /404/ [L]

# cond 2
RewriteCond %{REQUEST_FILENAME} !index\.php$
# cond 3
RewriteCond %{REQUEST_URI} \.php$
# rule 2
RewriteRule [^\.]*\.[a-zA-Z0-9]+$ /404/ [L]

# rule 3
RewriteRule ^(([^/\.]+)/?)*?$ /index.php [L]

然而,只有第二个区块能够满足我的需求。例如,第一个.htaccess - 无法重定向不存在的文件a.pdf,而是显示有关未找到文件的默认服务器消息。

有人可以向我解释一下吗?

1 个答案:

答案 0 :(得分:2)

你在第一个.htaccess中的OR条件的顺序错误。

[OR]标志围绕两个语句创建一个组,有效地将条件写为:

if (
    (FILE_NOT_FOUND or FILE_NAME === 'index.php')
    and REQUEST_URI ends in .php
) { ... }

按此顺序编写,条件将永远不会匹配以扩展名其他结尾的URI而不是PHP。

你真正想要的是:

if (
    (FILE_NOT_FOUND or REQUEST_URI ends in .php)
    and FILE_NAME !== 'index.php'
) { ... }

可以通过简单地重新排列两个相关的重写条件来表达:

RewriteCond %{REQUEST_FILENAME} !-f [OR]
RewriteCond %{REQUEST_FILENAME} \.php$
RewriteCond %{REQUEST_URI} !index\.php
RewriteRule [^\.]*\.[a-zA-Z0-9]+$ /404/ [L]

你甚至可以通过阅读自己的单词来解决你的错误(简化以显示你想到的实际条件):

  

我想要做的是重定向每个不存在的文件 [或] 每个.php文件,[和] 不是/index.php 到/ 404 /.

Here is a good StackOverflow question/answer关于[OR]在.htaccess文件中的优先顺序,如果您想了解更多关于mod_rewrite如何在内部实际运作的信息。