为什么mod_rewrite会重写两次?

时间:2023-02-10 11:22:27

I only recently found out about URL rewriting, so I've still got a lot to learn.

我最近才发现有关URL重写的问题,所以我还有很多需要学习的地方。

While following the Easy Mod Rewrite tutorial, the results of one of their examples is really confusing me.

在遵循Easy Mod Rewrite教程的同时,他们的一个示例的结果让我很困惑。

RewriteBase /
RewriteRule (.*) index.php?page=$1 [QSA,L]

Rewrites /home as /index.php?page=index.php&page=home.

重写/ home为/index.php?page=index.php&page=home。

I thought the duplicates might have had been caused by something in my host's configs, but a clean install of XAMPP does the same.

我认为副本可能是由我的主机配置中的某些东西引起的,但是XAMPP的干净安装也是如此。

So, does anyone know why this seems to parse twice?

那么,有谁知道为什么这似乎解析了两次?

And, to me this seems like, if it's going to do this, it would be an infinite loop -- why does it stop at 2 cycles?

而且,对我来说,这似乎是,如果要做到这一点,它将是一个无限循环 - 为什么它停止在2个周期?

2 个解决方案

#1


From Example 1 on this page, which is part of the tutorial linked in your question:

从本页的示例1开始,这是您的问题中链接的教程的一部分:

Assume you are using a CMS system that rewrites requests for everything to a single index.php script.

假设您正在使用CMS系统将一切请求重写为单个index.php脚本。

RewriteRule ^(.*)$ index.php?PAGE=$1 [L,QSA]

Yet every time you run that, regardless of which file you request, the PAGE variable always contains "index.php".

但是每次运行它时,无论您请求哪个文件,PAGE变量始终包含“index.php”。

Why? You will end up doing two rewrites. Firstly, you request test.php. This gets rewritten to index.php?PAGE=test.php. A second request is now made for index.php?PAGE=test.php. This still matches your rewrite pattern, and in turn gets rewritten to index.php?PAGE=index.php.

为什么?你最终会做两次重写。首先,您请求test.php。这会被重写为index.php?PAGE = test.php。现在为index.php?PAGE = test.php提出第二个请求。这仍然与您的重写模式匹配,然后被重写为index.php?PAGE = index.php。

One solution would be to add a RewriteCond that checks if the file is already "index.php". A better solution that also allows you to keep images and CSS files in the same directory is to use a RewriteCond that checks if the file exists, using -f.

一种解决方案是添加一个RewriteCond来检查文件是否已经是“index.php”。一个更好的解决方案,也允许您将图像和CSS文件保存在同一目录中是使用RewriteCond,使用-f检查文件是否存在。


1the link is to the Internet Archive, since the tutorial website appears to be offline

1该链接指向Internet Archive,因为教程网站似乎处于脱机状态

#2


From the Apache Module mod_rewrite documentation:

从Apache Module mod_rewrite文档:

'last|L' (last rule)
[…] if the RewriteRule generates an internal redirect […] this will reinject the request and will cause processing to be repeated starting from the first RewriteRule.

'last | L'(最后一条规则)[...]如果RewriteRule生成内部重定向[...],这将重新注入请求,并将导致从第一个RewriteRule开始重复处理。

To prevent this you could either use an additional RewriteCond directive:

为了防止这种情况,您可以使用额外的RewriteCond指令:

RewriteCond %{REQUEST_URI} !^/index\.php$
RewriteRule (.*) index.php?page=$1 [QSA,L]

Or you alter the pattern to not match index.php and use the REQUEST_URI variable, either in the redirect or later in PHP ($_SERVER['REQUEST_URI']).

或者您将模式更改为与index.php不匹配,并在重定向或稍后在PHP中使用REQUEST_URI变量($ _SERVER ['REQUEST_URI'])。

RewriteRule !^index\.php$ index.php?page=%{REQUEST_URI} [QSA,L]

#1


From Example 1 on this page, which is part of the tutorial linked in your question:

从本页的示例1开始,这是您的问题中链接的教程的一部分:

Assume you are using a CMS system that rewrites requests for everything to a single index.php script.

假设您正在使用CMS系统将一切请求重写为单个index.php脚本。

RewriteRule ^(.*)$ index.php?PAGE=$1 [L,QSA]

Yet every time you run that, regardless of which file you request, the PAGE variable always contains "index.php".

但是每次运行它时,无论您请求哪个文件,PAGE变量始终包含“index.php”。

Why? You will end up doing two rewrites. Firstly, you request test.php. This gets rewritten to index.php?PAGE=test.php. A second request is now made for index.php?PAGE=test.php. This still matches your rewrite pattern, and in turn gets rewritten to index.php?PAGE=index.php.

为什么?你最终会做两次重写。首先,您请求test.php。这会被重写为index.php?PAGE = test.php。现在为index.php?PAGE = test.php提出第二个请求。这仍然与您的重写模式匹配,然后被重写为index.php?PAGE = index.php。

One solution would be to add a RewriteCond that checks if the file is already "index.php". A better solution that also allows you to keep images and CSS files in the same directory is to use a RewriteCond that checks if the file exists, using -f.

一种解决方案是添加一个RewriteCond来检查文件是否已经是“index.php”。一个更好的解决方案,也允许您将图像和CSS文件保存在同一目录中是使用RewriteCond,使用-f检查文件是否存在。


1the link is to the Internet Archive, since the tutorial website appears to be offline

1该链接指向Internet Archive,因为教程网站似乎处于脱机状态

#2


From the Apache Module mod_rewrite documentation:

从Apache Module mod_rewrite文档:

'last|L' (last rule)
[…] if the RewriteRule generates an internal redirect […] this will reinject the request and will cause processing to be repeated starting from the first RewriteRule.

'last | L'(最后一条规则)[...]如果RewriteRule生成内部重定向[...],这将重新注入请求,并将导致从第一个RewriteRule开始重复处理。

To prevent this you could either use an additional RewriteCond directive:

为了防止这种情况,您可以使用额外的RewriteCond指令:

RewriteCond %{REQUEST_URI} !^/index\.php$
RewriteRule (.*) index.php?page=$1 [QSA,L]

Or you alter the pattern to not match index.php and use the REQUEST_URI variable, either in the redirect or later in PHP ($_SERVER['REQUEST_URI']).

或者您将模式更改为与index.php不匹配,并在重定向或稍后在PHP中使用REQUEST_URI变量($ _SERVER ['REQUEST_URI'])。

RewriteRule !^index\.php$ index.php?page=%{REQUEST_URI} [QSA,L]