.htaccess重写隐藏子目录时省略尾斜杠暴露子目录问题
问题场景与现象
域名example.com是主域名的别名,目标是将其指向主站点的example.com/子目录(该子目录下包含test/子目录)。当前使用的.htaccess规则如下:
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com$ [NC] RewriteRule ^(.*)?$ example.com/$1 [L,NC]
出现以下现象:
- 访问
https://example.com/test/(带尾斜杠)可正常显示./example.com/test/index.html,无URL跳转; - 访问
https://example.com/test(省略尾斜杠)时,会跳转到https://example.com/example.com/test/,暴露了不必要的子目录路径。
原因分析
这是Apache的mod_dir模块和当前Rewrite规则共同作用的结果:
- 当访问不带尾斜杠的目录(如
/test)时,mod_dir会默认触发301跳转,自动补全尾斜杠(目的是让服务器正确识别目录并返回默认索引文件); - 当前的Rewrite规则先将请求重写到
example.com/$1,此时mod_dir处理的是重写后的路径example.com/test,跳转时就会把这个真实子目录路径拼到原域名后,最终出现https://example.com/example.com/test/的跳转URL。
解决方案
要实现两种访问场景均无跳转且URL保持不变,需要调整Rewrite规则的逻辑,优先处理目录尾斜杠的问题,同时让mod_dir能正确识别重写后的路径,避免暴露真实子目录。修改后的.htaccess规则如下:
# 1. 先为example.com下的目录请求补全尾斜杠,直接在原域名下跳转 RewriteCond %{HTTP_HOST} ^(www\.)?example\.com$ [NC] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^(.*[^/])$ /$1/ [L,R=301,NC] # 2. 将example.com的请求重写到对应子目录,使用PT标志让后续模块正确处理 RewriteCond %{HTTP_HOST} ^(www\.)?example\.com$ [NC] RewriteRule ^(.*)$ /example.com/$1 [L,NC,PT]
规则说明:
- 第一条规则:仅针对
example.com域名,检测请求路径是否为真实目录(%{REQUEST_FILENAME} -d),如果是且末尾无斜杠,就跳转到带斜杠的URL,跳转过程不会暴露子目录; - 第二条规则:使用
PT(Pass Through)标志,让重写后的路径被mod_dir等后续模块正确识别,相当于告诉Apache“重写后的路径是内部路径,后续模块继续处理”,避免mod_dir跳转时带上真实子目录路径; - 两条规则的顺序不能颠倒,必须先处理尾斜杠跳转,再做子目录重写。
内容的提问来源于stack exchange,提问作者sl1p
相关产品推荐
相关产品推荐

