使用mod_rewrite实现内部重定向时遇文件夹存在导致循环的问题
解决Apache重写规则的目录循环问题
这个重定向循环问题我之前也碰到过,根源其实是Apache默认的DirectorySlash行为在搞鬼!
当你请求https://example.com/test,而test是服务器上真实存在的文件夹时,Apache会自动发送一个301重定向,把请求转到https://example.com/test/(带斜杠的版本)。如果你的重写规则没处理这种带斜杠的情况,或者没阻止这个默认重定向,就会陷入循环:Apache重定向到带斜杠的路径,你的规则又把它转回去,或者反复触发目录检查,导致无限循环。
下面给你两种靠谱的解决方案,按需选择:
思路1:禁用自动添加斜杠(简单直接)
关闭Apache自动给目录加斜杠的默认行为,这样请求/test时不会被强制重定向到/test/,直接由你的重写规则处理。
在.htaccess里添加以下规则:
# 禁用目录列表(可选但推荐,避免暴露文件夹内容) Options -Indexes # 关闭自动添加斜杠的重定向 DirectorySlash Off RewriteEngine On # 排除真实存在的文件,避免影响正常访问(比如直接打开template.php) RewriteCond %{REQUEST_FILENAME} !-f # 匹配不带斜杠的路径,重写到template.php并传递a参数 RewriteRule ^([^/]+)$ template.php?a=$1 [L,QSA] # 可选:处理用户手动输入带斜杠的情况 RewriteRule ^([^/]+)/$ template.php?a=$1 [L,QSA]
说明:
[L]flag表示这是最后一条规则,匹配后不再继续处理其他规则[QSA]flag会保留原请求的查询参数(比如/test?b=1会变成template.php?a=test&b=1)Options -Indexes可以防止别人访问你的文件夹时看到里面的文件列表,提升安全性
思路2:保留默认行为,调整规则避免循环
如果你不想关闭DirectorySlash,可以通过规则优先处理目录请求,提前拦截Apache的自动重定向:
RewriteEngine On # 1. 处理带斜杠的目录请求:如果是真实文件夹且带斜杠,直接重写 RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^([^/]+)/$ template.php?a=$1 [L,QSA] # 2. 处理不带斜杠的目录请求:直接重写,不让Apache触发重定向 RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^([^/]+)$ template.php?a=$1 [L,QSA] # 3. 处理非目录、非真实文件的普通请求 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^([^/]+)$ template.php?a=$1 [L,QSA]
这样不管用户请求的是/test还是/test/,都会被正确重写到template.php?a=test,不会触发循环。
内容的提问来源于stack exchange,提问作者Antict
相关产品推荐
相关产品推荐

