Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/apache/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache Mod_重写意外行为L标志_Apache_Mod Rewrite - Fatal编程技术网

Apache Mod_重写意外行为L标志

Apache Mod_重写意外行为L标志,apache,mod-rewrite,Apache,Mod Rewrite,我的web应用程序结构是: /var/www/myapp/ - www/ - index.php - css.php - .htaccess 虚拟主机配置为: <VirtualHost *:80> ServerName www.example.org DocumentRoot /var/www/myapp/www DirectoryIndex index.php index.ht

我的web应用程序结构是:

/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>
似乎发生了第一次重定向,但mod_重写并没有停止导致内部重定向。然后,更改后的url再次传递给mod_rewrite,并发生第二次重定向,但现在与第二条规则匹配

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


再次感谢您

您错过了有关以下方面的一个重要事实:

因此,如果您在这些[
.htaccess
]上下文中使用指令,您必须采取明确的步骤来避免规则循环,而不是仅仅依靠[L]标志来终止一系列规则的执行

发件人:;我敢说

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

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

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

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

如果URI更改,则L
将重新注入下一轮(外部循环),如下所示:

为了突出显示
L
标志的作用位置以及
内部重定向的发生位置,这是一个带有特定(第一个)URI重写注释的相同图形:

它显示
L
标志仅退出内部循环,但如果URI已被重写(更改)(如您的情况),则外部循环会注意将更改的URI再次传递给所有重写规则

相反,您可能希望制定一个条件,如手册该部分的以下示例所示:

RewriteBase /
RewriteCond %{REQUEST_URI} !=/index.php
RewriteRule ^(.*) /index.php?req=$1 [L,PT]
(,或多或少不是解决方案的一部分,只需注意,因为我引用了示例)

您实际想要使用的是
END
标志:

RewriteRule css css.php [END,NC]

但是,如果您有所需的apache版本(在2.3.9及更高版本中提供),请与系统管理员联系。如果没有,您需要使用。

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

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

    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]
    

请注意,对于这些示例中的每一个,您都需要为每个规则使用此结构。

这很有趣。设置看起来不错,我在我的系统上试过了,效果很好。也许你想打开重写日志,看看到底重写了什么:我已经编辑了消息,你会找到一个日志。只需关注内部重定向:-)请参阅@谢谢您的反馈。这是一个有点难以用语言来描述,所以我认为与图形这应该是更好的。很好的回答,我爱的图表!有史以来最好的mod_重写说明!我完全同意,这是一个极好的解释。另一个变体——但不适用于该变量——是将重写后的URL重写为自身,以便触发now change exit L解析(例如Apache 2.2)。
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]