2

我认为“L”标志应该防止应用后续规则。然而在这个例子中:

RewriteRule foo bar [L]
RewriteRule bar qux

我被http://mysite/foo重写为http://mysite/qux. 我预计http://mysite/bar。我在这里想念什么?

4

2 回答 2

1

mod_rewrite 介绍

请务必使用LogLevel指令将mod_rewrite 的日志级别配置为跟踪级别之一。在调试 mod_rewrite 配置问题时它是必不可少的,因为它会准确地告诉您每个规则是如何处理的。

要在 Apache 2.4 中打开 mod_rewrite 跟踪,您可以使用

LogLevel info mod_rewrite:trace3

但是,在 Apache 2.2(这是当前最喜欢的生产环境)中,您必须使用

RewriteLog "/var/log/apache2/rewrite.log"
RewriteLogLevel 3

你的配置

RewriteRule foo bar [L]
RewriteRule bar qux

是有问题的,因为它必须只运行一次才能按照您想要的方式工作。当规则用于目录或 .htaccess 上下文时,2.2 中的L 标志不会按照您的想法执行。

如果您在 .htaccess 文件或部分中使用 RewriteRule,那么了解规则的处理方式非常重要。其简化形式是,一旦处理了规则,重写的请求就会被交回 URL 解析引擎来做它可能做的事情。处理重写的请求时,可能会再次遇到 .htaccess 文件或部分,因此可能会从头开始再次运行规则集。最常见的情况是,如果其中一个规则导致重定向(内部或外部)导致请求过程重新开始。

但是,将这些规则移至服务配置或虚拟主机上下文确实有效。(在我的本地服务器上验证。)

通常,您要编写规则,因此处理多少次并不重要。如果您绝对不能这样做,我仍然不喜欢使用RewriteCond %{THE_REQUEST} ^GET\ /bar来避免循环甚至RewriteCond %{THE_REQUEST} ^[^ ]+ /bar但我目前对 Apache 2.2 没有建议。

Apache 2.4 有针对这种情况的END标志。

于 2013-05-19T06:06:52.920 回答
1

[L]标志的行为在 Apache 文档中描述得非常差。为了理解它是如何工作的,我们首先需要知道 Apache 如何处理 RewriteRules。举个简单的例子

RewriteRule ^something /somethingelse #1
RewriteRule ^somewhere /somewhereelse #2 
RewriteRule ^someplace /anotherplace  #3

在这种有多个规则且没有[L]标志的情况下,如果我们要 request /something,Apache 将重写它/somethingelse(根据 #1),然后尝试规则 #2 和 #3。处理完所有规则后,它会检查来自 RewriteRules 的 URL 是否与进入的 URL 相同。如果不是,Apache 会再次开始处理所有规则,直到 input===output(或最大数量满足重定向,以防止无限循环)。

现在,如果我们更改规则#1 并添加[L]到它,并且我们再次请求/something,Apache 将把它重写为/somethingelse(按照#1),然后停止处理规则,即它不会处理#2 和#3。但是,由于出现的 URL 与进入的 URL 不同(这是关键),处理重新开始,并且规则 #2 和 #3 无论如何都会被处理(并且 #1 也是,但没有不再做任何事)。

在您的示例中,如果您想防止被第一个 RewriteRule 重写时/bar被重定向到,您可以使用/qux

RewriteRule foo bar [L]
RewriteCond %{THE_REQUEST} ^GET\ /bar
RewriteRule bar qux

只有当用户特别请求时才会重写/bar,而不是如果 URL 被重写为first。/qux /bar/foo/bar

这里的技巧是%{THE_REQUEST}包含用于请求的确切 HTTP 标头,并且在您重写 URL 时不会更改,因此使用该变量您始终可以检查原始请求的用途(相比之下%{REQUEST_URI},确实会更改)每次重写)。

于 2013-05-19T06:35:37.090 回答