【问题标题】:Mod_Rewrite unexpected behavior L flagMod_Rewrite 意外行为 L 标志
【发布时间】:2012-07-14 03:29:37
【问题描述】:

我的网络应用结构是:

/var/www/myapp/
    - www/
        - index.php
        - css.php
        - .htaccess

虚拟主机配置为:

<VirtualHost *:80>
        ServerName www.example.org
        DocumentRoot /var/www/myapp/www
        DirectoryIndex index.php index.html
        <Directory /var/www/myapp/www>
                Options Indexes FollowSymLinks MultiViews
                AllowOverride All
                Order allow,deny
                allow from all
        </Directory>
</VirtualHost>

在 /var/www/myapp/www/.htaccess 中有:

<IfModule mod_rewrite.c>
    RewriteEngine on
    RewriteBase /
    RewriteRule css css.php [L,NC]
    RewriteRule .* index.php
</IfModule>

现在,如果我调用 www.example.org,我会正确重定向到 index.php,但如果我调用 www.example.org/css,我仍然会始终重定向到 index.php。

如果我删除“RewriteRule .* index.php”行,然后调用 www.example.org/css,我会正确重定向到 css.php。

怎么了? 非常感谢大家

======== 编辑=========

192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b7080058/initial] (3) [perdir /var/www/sviluppo/mattia_dev/example/www/] add path info postfix: /var/www/sviluppo/mattia_dev/example/www/DEV_2 -> /var/www/sviluppo/mattia_dev/example/www/DEV_2/css/example1/test.css
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b7080058/initial] (3) [perdir /var/www/sviluppo/mattia_dev/example/www/] strip per-dir prefix: /var/www/sviluppo/mattia_dev/example/www/DEV_2/css/example1/test.css -> DEV_2/css/example1/test.css
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b7080058/initial] (3) [perdir /var/www/sviluppo/mattia_dev/example/www/] applying pattern '^(DEV|TEST|PROD)\_[0-9]+\/(css|js|image|static)\/(.+)$' to uri 'DEV_2/css/example1/test.css'
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b7080058/initial] (2) [perdir /var/www/sviluppo/mattia_dev/example/www/] rewrite 'DEV_2/css/example1/test.css' -> 'css/example1/test.css'
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b7080058/initial] (3) [perdir /var/www/sviluppo/mattia_dev/example/www/] add per-dir prefix: css/example1/test.css -> /var/www/sviluppo/mattia_dev/example/www/css/example1/test.css
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b7080058/initial] (2) [perdir /var/www/sviluppo/mattia_dev/example/www/] trying to replace prefix /var/www/sviluppo/mattia_dev/example/www/ with /
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b7080058/initial] (5) strip matching prefix: /var/www/sviluppo/mattia_dev/example/www/css/example1/test.css -> css/example1/test.css
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b7080058/initial] (4) add subst prefix: css/example1/test.css -> /css/example1/test.css
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b7080058/initial] (1) [perdir /var/www/sviluppo/mattia_dev/example/www/] internal redirect with /css/example1/test.css [INTERNAL REDIRECT]
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b63188e8/initial/redir#1] (3) [perdir /var/www/sviluppo/mattia_dev/example/www/] strip per-dir prefix: /var/www/sviluppo/mattia_dev/example/www/css/example1/test.css -> css/example1/test.css
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b63188e8/initial/redir#1] (3) [perdir /var/www/sviluppo/mattia_dev/example/www/] applying pattern '^(DEV|TEST|PROD)\_[0-9]+\/(css|js|image|static)\/(.+)$' to uri 'css/example1/test.css'
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b63188e8/initial/redir#1] (3) [perdir /var/www/sviluppo/mattia_dev/example/www/] strip per-dir prefix: /var/www/sviluppo/mattia_dev/example/www/css/example1/test.css -> css/example1/test.css
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b63188e8/initial/redir#1] (3) [perdir /var/www/sviluppo/mattia_dev/example/www/] applying pattern '.*' to uri 'css/example1/test.css'
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b63188e8/initial/redir#1] (2) [perdir /var/www/sviluppo/mattia_dev/example/www/] rewrite 'css/example1/test.css' -> 'index.php'
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b63188e8/initial/redir#1] (3) [perdir /var/www/sviluppo/mattia_dev/example/www/] add per-dir prefix: index.php -> /var/www/sviluppo/mattia_dev/example/www/index.php
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b63188e8/initial/redir#1] (2) [perdir /var/www/sviluppo/mattia_dev/example/www/] trying to replace prefix /var/www/sviluppo/mattia_dev/example/www/ with /
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b63188e8/initial/redir#1] (5) strip matching prefix: /var/www/sviluppo/mattia_dev/example/www/index.php -> index.php
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b63188e8/initial/redir#1] (4) add subst prefix: index.php -> /index.php
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b63188e8/initial/redir#1] (1) [perdir /var/www/sviluppo/mattia_dev/example/www/] internal redirect with /index.php [INTERNAL REDIRECT]
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b6310db8/initial/redir#2] (3) [perdir /var/www/sviluppo/mattia_dev/example/www/] strip per-dir prefix: /var/www/sviluppo/mattia_dev/example/www/index.php -> index.php
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b6310db8/initial/redir#2] (3) [perdir /var/www/sviluppo/mattia_dev/example/www/] applying pattern '^(DEV|TEST|PROD)\_[0-9]+\/(css|js|image|static)\/(.+)$' to uri 'index.php'
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b6310db8/initial/redir#2] (3) [perdir /var/www/sviluppo/mattia_dev/example/www/] strip per-dir prefix: /var/www/sviluppo/mattia_dev/example/www/index.php -> index.php
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b6310db8/initial/redir#2] (3) [perdir /var/www/sviluppo/mattia_dev/example/www/] applying pattern '.*' to uri 'index.php'
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b6310db8/initial/redir#2] (2) [perdir /var/www/sviluppo/mattia_dev/example/www/] rewrite 'index.php' -> 'index.php'
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b6310db8/initial/redir#2] (3) [perdir /var/www/sviluppo/mattia_dev/example/www/] add per-dir prefix: index.php -> /var/www/sviluppo/mattia_dev/example/www/index.php
192.168.1.8 - - [14/Jul/2012:19:07:21 +0200] [www.example.org/sid#b747b6c0][rid#b6310db8/initial/redir#2] (1) [perdir /var/www/sviluppo/mattia_dev/example/www/] initial URL equal rewritten URL: /var/www/sviluppo/mattia_dev/example/www/index.php [IGNORING REWRITE]

似乎发生了第一次重定向,但 mod_rewrite 并没有停止导致内部重定向。然后,更改后的 url 再次传递给 mod_rewrite 并发生第二次重定向,但现在匹配第二条规则。

我无法理解,因为我放置了 [L] 标志只是为了确保 mod_rewrite 停止。

再次感谢

【问题讨论】:

标签: apache mod-rewrite


【解决方案1】:

您错过了关于L flag 的重要事实:

因此,如果您在这些 [.htaccess, &lt;Directory&gt;] 上下文之一中使用 RewriteRule 指令,那么重要的是,您应采取明确的步骤来避免规则循环,而不是仅仅依靠[L] 标志终止一系列规则的执行

发件人:L|last (Flag);由我加粗

这意味着,仅使用L 不会产生您想要的效果来防止内部重定向。 INTERNAL REDIRECT 发生在这里是因为它必须发生,您已经使用 .htaccess 配置指定了它。 L 标志不是阻止INTERNAL REDIRECT 的正确标志。

让我们仔细看看您的问题以及实际发生的情况:

我无法理解,因为我放置了 [L] 标志只是为了确保 mod_rewrite 停止。

只是您对L 标志的理解有误。它只会在当前重写时停止,这意味着它下面的RewriteRule 指令不会在当前轮次(内循环)中处理。

如果 URI 发生更改,L 将重新注入到下一轮(外循环)中,如以下 technical details flowchart 所示:

为了突出显示L 标志的位置和INTERNAL REDIRECT 发生的位置,这是同一张图,其中包含一些用于特定(第一次)URI 重写的注释:

它表明L 标志仅退出内部循环,但如果 URI 已被重写(更改) - 就像您的情况一样 - 外部循环会注意更改的 URI 将再次传递 em> 到你所有的重写规则。

相反,您可能希望按照手册该部分的以下示例来制定条件:

RewriteBase /
RewriteCond %{REQUEST_URI} !=/index.php
RewriteRule ^(.*) /index.php?req=$1 [L,PT]

PT has it's own manual entry, is 或多或少不是解决方案的一部分,只是注意到因为我按原样引用了示例)

您真正想要使用的是END 标志:

RewriteRule css css.php [END,NC]

但是,如果您有所需的 apache 版本(在 2.3.9 及更高版本中可用),请联系您的系统管理员。如果没有,则需要使用RewriteCond进行操作。

【讨论】:

  • 感谢您的反馈。这有点难以用语言来描述,所以我认为用图形应该会更好。
  • 很好的答案,我喜欢这些图表!
  • 有史以来最好的 mod_rewrite 插图!
  • 我完全同意,极好的解释。
【解决方案2】:

hakre 的回答很好地说明了正在发生的事情。除了使用END 标志之外,您还有更多选择:

  • 使用%{ENV:REDIRECT_STATUS} 防止任何进一步的重写。这将在内部重定向后发生变化。有关实际情况的更多信息,请参阅this page

    RewriteCond %{ENV:REDIRECT_STATUS} ^$
    RewriteRule css css.php [L,NC]
    
  • 使用%{THE_REQUEST} 匹配对服务器发出的请求。由于在内部重定向时这不会改变,因此可用于防止进一步的重定向

    RewriteCond %{THE_REQUEST} ^(GET|POST)\ /css\ HTTP
    RewriteRule ^ css.php [L,NC]
    
  • 在查询字符串中使用虚拟变量。这将允许通过在链接中定义此变量来防止重定向,但我们将在此处使用它来防止多次传递:

    RewriteCond %{QUERY_STRING} !noredir=1
    RewriteRule css css.php?noredir=1 [L,QSA,NC]
    

请注意,对于每个示例,您需要为每个单独的规则使用此结构。

【讨论】:

  • 另一种变体 - 但不适用于该变量 - 将重写的 URL 重写为自身,以便触发无更改退出现在 L 解析(例如 Apache 2.2)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-30
  • 1970-01-01
  • 2011-01-08
  • 2011-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多