这些规则:
RewriteEngine On
RewriteRule ^([^/]*)$ /index.php?page=$1 [L]
导致内部重写循环。重写引擎循环遍历所有规则,直到达到内部重定向限制(从而导致 500 服务器错误)或从引擎出来的结果 URI 与进入它的 URI 相同。此外(这是一个非常重要的概念),在将 URI 的前导斜杠发送到 htaccess 文件中的规则的重写引擎之前,它会被删除。所以我们有:
- 发出请求:http://domain.com/blah
- URI = /blah
- 去除前导斜杠,URI = blah
-
blah 匹配
^([^/]*)$,应用规则,URI = /index.php?page=blah
-
blah 不等于 /index.php
- 规则循环,URI = /index.php
- 去除前导斜杠,URI = index.php
-
index.php 匹配
^([^/]*)$,应用规则,URI = /index.php?page=index.php
-
index 不等于 /index.php
- 规则循环,URI = /index.php
- 去除前导斜杠,URI = index.php
-
index.php 匹配
^([^/]*)$,应用规则,URI = /index.php?page=index.php
-
index 不等于 /index.php
等等
你有几个选择来处理这个问题。最简单的方法是从目标中删除 /:
RewriteRule ^([^/]*)$ index.php?page=$1 [L]
这将使得在上面的第 9 步中,index 将等于 index.php,从而停止重写过程(在第二次应用之前)。唯一的缺点是如果您需要重定向,或者如果 htaccess 文件被移动,目标中的相对 URI 有时会被误认为是文件路径而不是 URL 路径(apache 猜测这个,有时 apache 猜测错误的)。这可以通过包含一个基础来解决:
RewriteBase /
RewriteRule ^([^/]*)$ index.php?page=$1 [L]
您还可以添加条件以使其指向现有资源的 URL 将排除此规则的应用:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]*)$ /index.php?page=$1 [L]
因此,如果 URI 指向现有文件或目录,则跳过该规则。因此,在 URI 变为 /index.php 时第一次重写后,由于该文件存在,因此第二次跳过该规则。这也使得对文档根目录中的图像、css、脚本或静态页面的请求不会通过index.php 路由。如果这不是您想要的,如果 URI 已经是 index.php,您也可以直接跳过:
RewriteCond %{REQUEST_URI} !^/index.php
RewriteRule ^([^/]*)$ /index.php?page=$1 [L]