Apache下请求路由至子目录时URL显示异常的问题排查
解决Apache请求转发至符号链接目录时的URL跳转问题
问题场景
目录结构如下:
/webroot current # 指向releases下某版本的符号链接 releases release1 index.html en index.html release2 index.html en index.html ... .htaccess
需通过.htaccess将所有请求内部转发至current目录,浏览器URL保持不变(如请求/en时,实际指向/current/en,但URL显示https://example.com/en)。当前带尾斜杠的请求(如https://example.com/en/)正常,但不带尾斜杠时,URL会跳转为https://example.com/current/en。
原配置问题分析
原.htaccess配置:
Options +FollowSymlinks -MultiViews -Indexes DirectorySlash On RewriteEngine on RewriteBase / RewriteCond %{REQUEST_URI} !^/current/ RewriteCond %{ENV:REDIRECT_STATUS} ^$ RewriteRule ^(.*)$ current/$1 [L]
问题根源:当请求不带尾斜杠的目录(如/en)时,重写规则先将其转为current/en,Apache的mod_dir模块因DirectorySlash On,会对这个真实目录路径执行301跳转添加尾斜杠,导致浏览器URL暴露current路径。
解决方案
方案1:先给目录请求添加尾斜杠再转发
先对所有不带尾斜杠的目录请求添加尾斜杠,再转发至current,确保mod_dir处理的是原请求路径:
Options +FollowSymlinks -MultiViews -Indexes DirectorySlash On RewriteEngine on RewriteBase / # 为不带尾斜杠的目录请求添加尾斜杠(301跳转,保持原URL前缀) RewriteCond %{REQUEST_FILENAME} -d RewriteCond %{REQUEST_URI} !/$ RewriteRule ^(.*)$ /$1/ [L,R=301] # 转发非current路径的请求到current目录 RewriteCond %{REQUEST_URI} !^/current/ RewriteRule ^(.*)$ current/$1 [L]
方案2:使用PT标志传递重写路径
通过PT(Pass Through)标志,让重写后的路径被当作URL路径继续处理,而非文件系统路径,这样mod_dir处理目录尾斜杠时会基于原请求URL:
Options +FollowSymlinks -MultiViews -Indexes DirectorySlash On RewriteEngine on RewriteBase / RewriteCond %{REQUEST_URI} !^/current/ RewriteCond %{ENV:REDIRECT_STATUS} ^$ RewriteRule ^(.*)$ current/$1 [PT,L]
日志验证说明
原日志显示请求en被重写为current/en后触发内部重定向,mod_dir对current/en执行尾斜杠跳转,导致URL变更。使用上述方案后,mod_dir会基于原请求路径(如/en)添加尾斜杠,再转发至current/en/,浏览器URL始终保持为https://example.com/en/(或原请求的/en经跳转后变为/en/,但不会暴露current)。
内容的提问来源于stack exchange,提问作者rodskagg
相关产品推荐
相关产品推荐

