使用否定正则表达式条件的.htaccess中的RewriteCond不起作用?

时间:2011-01-28 04:53:10

标签: regex apache .htaccess mod-rewrite

我试图阻止(在这种情况下是WordPress)重写某些URL。在这种情况下,我试图阻止它在uploads目录中处理请求,而是将它们留在服务器的404页面中。所以我假设它就像添加规则一样简单:

RewriteCond %{REQUEST_URI} !^/wp-content/uploads/

此规则应评估为false并使这些请求的规则链失败,从而停止重写。但是没有......也许我需要在表达中匹配封面的完整字符串?

RewriteCond %{REQUEST_URI} !^/wp-content/uploads/.*$

不,那也不是。所以在抓了我的头后,我做了一个理智的检查。也许实际模式有问题。所以我做了一个简单的测试用例。

RewriteCond %{REQUEST_URI} ^/xyz/$

在这种情况下,当且仅当请求的URL是/ xyz /并且显示服务器的任何其他页面的404页面时,才会发生重写。这正是我的预期。所以我只会坚持下去!否定这种模式。

RewriteCond %{REQUEST_URI} !^/xyz/$

现在我期待看到与上述情况完全相反的情况。对于/ xyz /,不应该对每个其他可能的URL进行重写。相反,重写发生在每个URL上,包括/ xyz /和其他URL。

所以,在RewriteConds中使用否定的正则表达式在Apache中被破坏了,或者有一些基本的我不明白它。它是哪一个?

服务器是Apache2。

整个文件:

<IfModule mod_rewrite.c>
RewriteEngine On

RewriteBase /
RewriteRule ^index\.php$ - [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/wp-content/uploads/
RewriteRule . /index.php [L]
</IfModule>

WordPress的默认文件加上我的规则。

4 个答案:

答案 0 :(得分:9)

<IfModule mod_rewrite.c>
RewriteEngine On

RewriteBase /
RewriteRule ^index\.php$ - [L]

RewriteCond %{REQUEST_URI} !^/wp-content/uploads/ [OR]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule . /index.php [L]
</IfModule>

答案 1 :(得分:7)

所以,在经历了很多烦恼之后,我想出了问题。事实证明,我原来问题中的规则确实完全符合预期。其他一些做同样事情的方法也是如此,例如

RewriteRule ^wp-content/uploads/.*$ - [L]

(如果模式匹配,则将规则标记为最后一个)或

RewriteRule ^wp-content/uploads/.*$ - [S=1]

(如果模式匹配,则跳过下一条规则)以及问题中的否定规则,如上所述。所有这些规则都运行得很好,并且无需重写即可将控制权交还给Apache。

处理完这些规则后,问题就出现了。相反,问题是我删除了我的主机提供的默认404.shtml,403.shtml等模板。如果你没有任何.htaccess重写,那就可以了。服务器将打开自己的默认404页面,一切正常。 (至少这是我的想法,但实际上它是双重错误“另外,在尝试使用ErrorDocument来处理请求时遇到404 Not Found错误。”)

另一方面,当你有.htaccess时,它会再次执行404页面。如果页面在那里,它将被使用,但是现在,而是对catch. all规则捕获404.shtml的请求并将其重写为index.php。出于这个原因,我在这里或其他地方提出的所有其他建议都失败了,因为最后404页面已被重写为index.php。

因此,解决方案只是恢复错误模板。回想起来删除它们是非常愚蠢的,但我有这种“从头开始”的心态。不要想要任何看似不必要的东西。至少现在我明白发生了什么,这就是我想要的。

最后对Cecil发表评论:我从不想禁止访问任何内容,只是停止重写。现在并不重要,但我只是想澄清一下。

答案 2 :(得分:3)

如果/wp-content/uploads/确实是所请求的URI路径的前缀,那么您的规则应该按预期工作。

但是因为它显然不起作用,在文档根目录中的.htaccess文件的情况下,尽量不要匹配完整URI路径的路径前缀,而只匹配没有上下文每目录路径前缀的剩余路径没有前导/

的URI路径
RewriteCond $0 !^wp-content/uploads/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .+ /index.php [L]

如果这两者都不起作用,那么通过使用logging feature来深入了解mod_rewrite的重写过程肯定会有所帮助。因此,请将RewriteLogLevel设置为至少4的级别,发出请求并查看使用RewriteLog指定的日志文件中的条目。在那里,您可以看到mod_rewrite如何处理您的请求,RewriteLogLevel大于或等于4,您还会看到%{REQUEST_URI}等变量的值。

答案 3 :(得分:0)

使用“ WordPress First”方法时,我发现了许多类似的示例。例如,添加:

ErrorDocument 404 /error-docs/404.html

.htaccess文件处理消息(“此外,还有404未找到错误...”)。