Apache GeoIP重定向带?参数页面报重定向过多问题排查
问题根因
死循环是重写规则触发逻辑导致的,和GeoIP检测本身无关:
- 跳转到
info.html正常,是因为这个文件真实存在于服务器上,跳转后的二次请求会被你原有核心规则里的!-f条件(请求目标不是真实文件才转发到index.php)排除,不会再走重写流程,自然不会重复触发GeoIP跳转。 - 跳转到带
lang=de参数的地址时,请求目标是站点根路径,没有对应实体文件,二次请求会再次被核心规则转发到index.php,此时GeoIP检测到来源还是德国IP,会再次触发跳转,反复执行就报重定向次数过多。 - 你写的GeoIP规则里的
$1是无效值,当前匹配正则没有分组,这个变量不会替换成任何内容,属于冗余写法,不影响核心逻辑但建议删掉。
修复方法
不要修改你原有的核心路由规则,只需要按如下方式调整GeoIP规则即可:
- 把GeoIP规则挪到所有重写规则的最开头,优先于核心路由规则执行
- 添加循环终止判断:如果请求已经带了
lang=de参数,就不再触发重定向,从根源切断循环 - 删掉无效的
$1变量,临时调试阶段先用302临时跳转,避免浏览器缓存坏规则
调整后的完整.htaccess规则如下:
RewriteEngine On # 德国IP重定向规则 必须放在核心路由规则之前 RewriteCond "%{ENV:GEOIP_COUNTRY_CODE}" ^DE$ # 已经带lang=de参数的请求不再跳转,避免死循环 RewriteCond %{QUERY_STRING} !lang=de [NC] RewriteRule ^/?index\.php$ http://de.example.com/?lang=de [L,R=302] # 原有核心规则 保持原样不要修改 RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^ index.php [QSA,L]
调试注意事项
- 调试阶段绝对不要先用301永久重定向,否则浏览器会缓存错误的跳转结果,每次改完规则要清缓存非常麻烦,等测试完全正常再把
R=302换成R=301 - 不要优先用浏览器测重定向,优先用curl看响应头排查,避免缓存干扰,测试命令参考:
curl -I -H "X-Forwarded-For: 德国测试IP" http://你的站点地址,看返回的Location字段是否符合预期,有没有连续多个跳转响应 - 如果需要保留用户原请求带的其他参数,可以给GeoIP的RewriteRule加上QSA标记,即最后改成
[L,R=302,QSA],原请求的参数会自动拼接到lang=de后面
内容的提问来源于stack exchange,提问作者Serge
相关产品推荐
相关产品推荐

