【问题标题】:How to stop RewriteEngine/PHP redirect loop?如何停止 RewriteEngine/PHP 重定向循环?
【发布时间】:2015-12-20 09:25:34
【问题描述】:

任务看起来很简单:

所有请求都必须通过一个文件传递。

然而,

当以下代码添加到 httpd.conf 时:

RewriteEngine On  
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^(.*)$ /index.php?route=$1 [QSA,R=301,L]

以下代码被添加到/index.php:

if( isset($_GET["route"]) && $_GET["route"] != "/index.php" ){
header("Location: ".$_GET["route"]);
}

然后它会导致重定向循环!

导致例如这样的循环:

www.site.com/image.jpg ->(由 httpd.conf 重定向)

www.site.com/index.php?route=/image.jpg ->(由 index.php 重定向)

www.site.com/image.jpg ->(由 httpd.conf 重定向)

www.site.com/index.php?route=/image.jpg ->(由 index.php 重定向)

...

所以,问题如下:

如何停止这个循环?

例如以这种方式停止:

www.site.com/image.jpg ->(由 httpd.conf 重定向)

www.site.com/index.php?route=/image.jpg ->(由 index.php 重定向)

www.site.com/image.jpg(没有进一步的重定向)

【问题讨论】:

  • 您究竟想用这个重写/重定向方案完成什么?这将有助于找到解决方案。
  • @amarnasan 它写在消息的开头 - 所有请求都必须通过一个文件传递(在本机处理请求开始之前执行一些额外的操作)

标签: php apache .htaccess mod-rewrite redirect


【解决方案1】:

你为什么要放这个:

RewriteEngine On  
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^(.*)$ /index.php?route=$1 [QSA,R=301,L]

在 httpd.conf 中?您需要将其放入名为 .htaccess 的文件中,然后将其创建到您的根目录中。

【讨论】:

  • 如果他想把它放在 httpd.conf 中呢?
  • @konstantin-rachev “允许 .htaccess 文件会导致性能下降”(apache 手册)
  • 这是一个解决方案吗?允许性能下降?通过加快速度来停止循环?
  • @amarnasan 这是一个解决方案吗?放入.htaccess?这不会停止循环。
  • 我不是提出该解决方案的人。我是那个说这不是解决方案的人。
【解决方案2】:

首先,把它放到 .htaccess 文件中,而不是放在 httpd.conf 中

RewriteEngine On  
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /index.php [QSA,R=301,L]

然后,从您的 index.php 文件中删除此重定向。您可以通过 $_GET 或 $_REQUEST 获取所有变量。

【讨论】:

  • 首先:“允许 .htaccess 文件会导致性能下降”(apache 手册)。然后:RewriteEngine 重写提到的变量。
  • @user3119308 当然可以。但是,如果您只处理一个 .htaccess 文件,您将永远不会注意到这种性能损失。
【解决方案3】:

多么愚蠢的解决方案。当然会导致重定向循环。在 RewriteCond-s 中,您尝试捕获服务器文件系统中不存在的文件和目录名称,然后您尝试将它们的名称传递给 index.php,在其中一次又一次地请求它们。

【讨论】:

  • 如果没有这样的RewriteCond-s,那就不能解决问题。所以,这不是一个解决方案。此外,在这种情况下 $_SERVER[SCRIPT_NAME] 不会显示真正请求的文件(在通过 DirectoryIndex 命令重定向之后)。
  • 问题不在于你的 RewriteCond 本身,而在于你的 /index.php 中的发送头 302,文件或目录名不存在,这导致再次触发重写规则。
【解决方案4】:

您的规则看起来不错,但 R=301 在您的规则中有点奇怪,因为您不想在浏览器中公开您的内部 URL。

但是由于这种情况,PHP 代码看起来很可疑:

$_GET["route"] != "/index.php" 

由于这些条件,/index.php 本身不会通过此规则路由,因此始终为 true

RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f

因此,您的代码将通过使用header 函数不断重定向而导致重定向循环。

我建议你保持这样的规则:

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)$ /index.php?route=$1 [QSA,L]

你的 PHP 代码应该只检查 $_GET['route'] 的存在,但不应该做任何重定向。

【讨论】:

    【解决方案5】:

    有一个样板可能会派上用场,它应该放在顶部,在 RewriteEngine on condition 之后:

    RewriteEngine on
    RewriteCond %{ENV:REDIRECT_STATUS} !^[\s/]*$
    RewriteRule ^ - [L]
    

    添加了一个环境,理论上可以,但是我只测试过一次,看看它是否可以解决问题。

    【讨论】:

    • 对不起,也许在其他情况下这是一个很好的解决方案,但在这种情况下不是,因为它完全避免了重定向,但在这种情况下,仍然需要一个重定向(到 index.php 并返回) .
    【解决方案6】:

    这个有点补丁,但我认为它有效。

    httpd.conf:

    RewriteCond %{SCRIPT_FILENAME} !-d
    RewriteCond %{SCRIPT_FILENAME} !-f
    RewriteCond %{QUERY_STRING} !^(.*)a=a$ [NC]
    RewriteRule ^(.*) index.php?route=$1 [QSA,L]
    

    index.php:

    <?php
    if( isset($_GET["route"]) && $_GET["route"] != "/index.php" ){
        header("Location: ".$_GET["route"].'?a=a');
    }
    

    问题是:重写引擎第一次将页面重定向到index.php。然后,在index.php 中重定向到同一个文件,但添加了参数a=a。然后重写引擎又来了,但是在查询字符串中找到字符串a=a时,他有不重定向的命令,并且没有进一步的重定向。

    当然,这会以 404 错误结束,因为您仅使用前两个 rewritecond 过滤不存在​​的文件,但我想您知道如何处理它。

    【讨论】:

    • 完全符合预期!非常感谢您的解决方案!
    猜你喜欢
    • 1970-01-01
    • 2018-05-12
    • 2021-11-27
    • 2012-06-19
    • 2014-02-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-21
    • 1970-01-01
    相关资源
    最近更新 更多