Apache Rewrite规则问题:URL中%23转#后路径缺失如何修复?
Apache Rewrite规则修复:保留完整路径将%23转换为#
问题
需要把URL domain.xyz/xyz/wtc/id%23name 重定向为 domain.xyz/xyz/wtc/id#name,但当前最后一条Rewrite规则执行后,URL丢失了/xyz前缀,变成domain.xyz/wtc/id#name。
当前使用的Rewrite规则:
# 如果目录或文件存在,直接访问 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d # 否则转发到index.php RewriteRule . index.php RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s(.*)/index\.php(.*) [NC] RewriteRule ^(.*)index\.php(.*)$ http://%{HTTP_HOST}$1/$2 [R=301,L,NE] RewriteRule ^(.*#.*) /$1 [R,NE]
原因
最后一条规则的问题在于:Apache会自动将%23解码为#,而#属于URL片段,Rewrite规则默认只匹配#之前的路径部分,导致$1无法捕获包含/xyz的完整原始路径;同时直接用/$1会错误截断路径前缀。
解决方案
利用THE_REQUEST变量获取浏览器发送的原始请求行(该变量不会被之前的Rewrite规则修改,且保留未解码的%23),调整后的规则如下:
# 处理%23转#的重定向,保留完整路径 RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s(/[^?\s]*%23[^?\s]*) [NC] RewriteRule ^ http://%{HTTP_HOST}%1 [R=302,L,NE] # 如果目录或文件存在,直接访问 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d # 否则转发到index.php RewriteRule . index.php RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s(.*)/index\.php(.*) [NC] RewriteRule ^(.*)index\.php(.*)$ http://%{HTTP_HOST}$1/$2 [R=301,L,NE]
关键说明
- 规则顺序:把处理
%23的规则放在最前面,确保请求被转发到index.php前完成重定向。 THE_REQUEST变量:(/[^?\s]*%23[^?\s]*)捕获从根目录开始的完整原始路径(包含%23),保证/xyz不会丢失。NE标志:禁止Apache对%23二次编码,使其直接转换为#。- 重定向类型:先用
R=302临时重定向测试,确认结果符合预期后,再改为R=301永久重定向。
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

