.htaccess重写规则优化:如何精简合并多条URL重写指令
Apache URL重写规则精简优化方案
你原来拼凑的规则冗余度高,会触发不必要的多次重定向,且规则顺序缺少终止标志容易出现逻辑冲突。四个需求里,强制HTTPS和移除www前缀属于同类型的域名/协议层跳转,可以合并为单条规则减少跳转次数,但后缀处理、斜杠移除属于路径层操作,和域名层逻辑天然无法合并到单条规则——之前合并失败就是因为把对外跳转和服务器内部重写的逻辑混在了一起。
原规则存在的具体问题
- 强制HTTPS和移除www前缀拆成2条规则,访问
http://www.example.com这类地址时会触发2次跳转,先跳转到http的非www域名,再跳转到https版本,增加不必要的请求开销 - 规则没有加
L(停止当前轮次重写)标志,规则间容易互相匹配触发死循环 - .php后缀的内部重写规则放在了外部跳转前面,容易出现重写后又触发跳转的逻辑冲突
- 补全.php后缀时没有判断对应文件是否存在,会把所有不带点的路径都尝试加上.php,触发不必要的404
精简后的可靠配置
RewriteEngine On Options +FollowSymLinks # 单条规则同时完成强制HTTPS + 移除www前缀,仅触发1次外部跳转 RewriteCond %{HTTPS} !on [OR] RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC] RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC] RewriteRule ^ https://%1%{REQUEST_URI} [L,R=302] # 移除非目录路径的末尾斜杠 RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)/$ /$1 [L,R=302] # 外部跳转移除路径中的.php后缀,禁止用户直接访问带后缀的地址 RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /([^\s]+)\.php(\?.*)?\s RewriteRule ^/?(.*)\.php$ /$1 [L,R=302] # 内部重写补全.php后缀,不对用户可见 RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME}.php -f RewriteRule ^([^.]+)$ $1.php [L]
使用注意事项
- 先保留
R=302临时跳转测试所有规则正常运行后,再替换为R=301永久跳转,301跳转浏览器会强制缓存,调试阶段不要提前开启 - 所有外部跳转规则都放在内部重写规则前面,避免内部重写的路径被对外暴露
- 如果你的站点有子目录存放静态资源不需要走php重写,可以在最后一步内部重写前加对应目录的排除条件
内容的提问来源于stack exchange,提问作者Tim
相关产品推荐
相关产品推荐

