如何停止RewriteEngine / PHP重定向循环?

时间:2015-09-23 07:09:14

标签: php apache .htaccess mod-rewrite redirect

任务看起来很简单:

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

然而,

将以下代码添加到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(无需进一步重定向)

6 个答案:

答案 0 :(得分:1)

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

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

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

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

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']的存在,但不应该执行任何重定向。

答案 1 :(得分:1)

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

的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过滤不存在​​的文件,但我想您知道如何处理它。

答案 2 :(得分:0)

首先,将此文件放在.htaccess文件中,而不是httpd.conf

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

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

有一个样板可以派上用场,它应该放在顶部,在RewriteEngine之后的条件:

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

添加了一个env,它按理论工作,但是我只测试了一次,看看它是否能解决问题。

答案 5 :(得分:-1)

你为什么这样说:

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

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