我有一个 Wordpress 网站。我想将 .php 网址重定向到没有 .php 后缀的网址。.htaccess 如下:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(.*)\.php$ "$1" [R=301,L,NC]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
但当我访问https://www.example.com/somepage.php,页面无法显示,浏览器显示如下错误:
The page isn’t redirecting properly
An error occurred during a connection to www.example.com.
This problem can sometimes be caused by disabling or refusing to accept cookies.
地址栏中的 url 变为 https://www.example.com/index。
如果我将重写规则更改为:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(.*)\.html$ "$1" [R=301,L,NC]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
并参观https://www.example.com/somepage.html,成功重定向至https://www.example.com/somepage网页可以正常显示,为什么?
答案1
因为,由于重定向是无条件的,你最终再次重定向后URL 已被重写为index.php
(WordPress 前端控制器)。
当您请求时/somepage.php
:
- 您被重定向到
/somepage
(根据第一条规则)。重定向响应被发送回客户端。 - 在第二次请求时,由最后一条规则
/somepage
内部重写为/index.php
。然后重写引擎重新开始(在目录语境)... /index.php
被重定向到/index
(根据第一条规则)。重定向响应被发送回客户端。- 第三次请求
/index
在内部被/index.php
最后一次重写。然后重写引擎重新开始... - 转到 3(陷入无限重定向循环)。
在一个目录上下文(如.htaccess
)重写引擎不会简单地单次传递脚本。它会循环执行,直到 URL 未经更改地传递。(除非您END
在 Apache 2.4 上使用该标志,或者发生外部 3xx 重定向。)
更改为删除.html
可以正常工作,因为您正在重写为/index.php
,它不以结尾.html
,所以重定向指令(删除.html
)不匹配。
要解决此问题,您需要避免重定向重写的请求。您可以通过以下任一方式执行此操作:
END
在最后一次重写时使用标志(Apache 2.4+),而L
不是阻止重写引擎的任何进一步循环。尽管您应该避免更改库存 WordPress 指令(见下文),但这可能不是首选选项。这在 Apache 2.2 上也不起作用。或者,检查服务器变量
.php
的扩展THE_REQUEST
(该变量包含 HTTP 请求标头的初始行,并且在重写请求时不会更改)。例如:# Remove ".php" extension on "direct" (not rewritten) requests only RewriteCond %{THE_REQUEST} [A-Z]{3,7}\s/[^?]+\.php(?:\?|\s|$) [NC] RewriteRule (.+)\.php$ /$1 [R=301,L,NC]
或者,检查
REDIRECT_STATUS
环境变量,该变量在初始请求时为空,在第一次成功重写时设置为 200(如 200 OK HTTP 状态)(这比上面更复杂的正则表达式更简单)。例如:# Remove ".php" extension on "direct" (not rewritten) requests only RewriteCond %{ENV:REDIRECT_STATUS} ^$ RewriteRule (.+)\.php$ /$1 [R=301,L,NC]
但是,您不应该编辑该部分内的代码# BEGIN WordPress
,因为 WordPress 本身会尝试维护这一点,并且可能会在以后覆盖此代码。这条规则需要取消前注释标记# BEGIN WordPress
。您不需要重复RewriteEngine On
文件后面出现的指令(在 WordPress 部分)。
您需要在测试之前清除浏览器缓存,因为错误的(永久)重定向很可能已被浏览器缓存。请先使用 301(临时)重定向进行测试,以避免缓存问题。
但是,仅凭这一点还不能让您访问.php
没有扩展名的文件.php
。因为无扩展名的 URL 需要在内部重写回文件.php
。