.htaccess配置问题:去除尾部斜杠规则失效引发404错误
解决.htaccess去除URL尾部斜杠无效且返回404的问题
我用PHP搭建了一个无数据库的简单网站,通过.htaccess配置了几个规则:强制HTTPS、强制URL带www前缀、去除.php扩展名、去除URL尾部斜杠。但去除尾部斜杠的规则不起作用,访问带尾部斜杠的URL(比如https://www.example.com/page/)会返回404错误,希望能把这类URL重定向到无尾部斜杠的正常地址,而不是报错。当前的.htaccess代码如下:
ErrorDocument 404 /errors/404.php Options -MultiViews <IfModule mod_rewrite.c> # (1) RewriteEngine On # (2) Options +FollowSymlinks </IfModule> # to https <IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{HTTPS} !=on RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R] # to 301 </IfModule> # force www at beginning <IfModule mod_rewrite.c> RewriteEngine On # # (1) RewriteCond %{HTTPS} =on RewriteRule ^ - [E=PROTO:https] RewriteCond %{HTTPS} !=on RewriteRule ^ - [E=PROTO:http] # # (2) # # RewriteCond %{HTTPS} !=on RewriteCond %{HTTP_HOST} !^www\. [NC] RewriteCond %{SERVER_ADDR} !=127.0.0.1 RewriteCond %{SERVER_ADDR} !=::1 RewriteRule ^ %{ENV:PROTO}://www.%{HTTP_HOST}%{REQUEST_URI} [L,R] # <- for test, for prod use [L,R=301] </IfModule> # remove .php <IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^([^\.]+)$ $1.php [NC,L] </IfModule> # remove trailing / <IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_URI} (.*)/$ RewriteRule ^(.*)/$ $1 [L,R] # <- for test, for prod use [L,R=301] </IfModule>
问题原因
当前规则顺序错误,去除.php扩展名的规则在尾部斜杠去除之前执行。当访问带斜杠的URL时,服务器会将其识别为目录(即使实际不存在),导致.php扩展名规则不触发,最终返回404。另外,多个独立的<IfModule mod_rewrite.c>块和重复的RewriteEngine On可能引发规则冲突。
修正后的完整.htaccess代码
ErrorDocument 404 /errors/404.php Options -MultiViews +FollowSymlinks <IfModule mod_rewrite.c> RewriteEngine On # 强制HTTPS(生产环境用R=301,测试可改R) RewriteCond %{HTTPS} !=on RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] # 强制www前缀(本地开发环境跳过) RewriteCond %{HTTP_HOST} !^www\. [NC] RewriteCond %{SERVER_ADDR} !=127.0.0.1 RewriteCond %{SERVER_ADDR} !=::1 RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301] # 去除URL尾部斜杠(排除真实存在的目录) RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_URI} (.+)/$ RewriteRule ^ %1 [L,R=301] # 去除.php扩展名(仅当对应php文件存在时触发) RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME}.php -f RewriteRule ^([^\.]+)$ $1.php [NC,L] </IfModule>
关键调整说明
- 合并规则块:把所有Rewrite规则放到同一个
<IfModule mod_rewrite.c>块里,避免重复启用RewriteEngine导致的冲突。 - 调整规则顺序:先处理HTTPS、www跳转,再处理尾部斜杠去除,最后处理.php扩展名隐藏。这样带斜杠的请求会先被重定向到无斜杠地址,再匹配扩展名规则。
- 优化尾部斜杠规则:用
%{REQUEST_FILENAME} !-d排除真实目录,防止影响正常目录访问;正则(.+)/$确保只匹配非空的带斜杠路径。 - 增强扩展名规则:添加
%{REQUEST_FILENAME}.php -f条件,只有当对应的PHP文件存在时才触发规则,减少无效匹配。
内容的提问来源于stack exchange,提问作者Peter-L
相关产品推荐
相关产品推荐

