500错误且日志提示“request exceeded the limit of 10 internal redirects”即为重写循环;主因是缺失rewritecond !-f/!-d排除真实文件目录、规则无[l]终止或目标路径被自身规则重复匹配。

重写规则陷入死循环,最典型表现是 Apache 返回 500 Internal Server Error,错误日志里出现类似 Request exceeded the limit of 10 internal redirects 的提示。这不是语法报错,而是引擎在反复匹配-重写-再匹配中触达了安全上限。
确认是否真发生了循环
先看错误日志(通常是 /var/log/apache2/error.log 或 /var/log/httpd/error_log),搜索关键词 redirect 或 loop。如果看到连续多次匹配同一规则、或重写目标又被自身规则捕获,基本可判定为循环。
- 例如规则
RewriteRule ^(.*)$ index.php [L]在没有前置条件时,会把index.php本身也匹配进去,导致无限递归 - 又如
RewriteRule ^/api/(.*)$ /index.php?route=api/$1 [L],若index.php路径也在/api/匹配范围内,也会触发二次匹配
检查 RewriteCond 是否缺失或写错
绝大多数循环源于缺少对真实文件和目录的排除判断。所有“统一入口”类规则(如前端控制器)必须加这两行:
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
-
RewriteCond %{REQUEST_FILENAME} !-f—— 当前请求不是真实存在的文件 -
RewriteCond %{REQUEST_FILENAME} !-d—— 当前请求不是真实存在的目录
漏掉任一条件,静态资源(如 index.php、favicon.ico)就可能被反复重写。注意:这两行必须写在 RewriteRule 之前,且顺序不能颠倒。
验证 [L] 标志是否被忽略或覆盖
[L] 表示“最后一条”,但它的作用范围仅限于当前轮次处理。如果规则链中某条没加 [L],后续规则仍会执行,可能形成隐式循环。
- 错误写法:
RewriteRule ^old/(.*)$ /new/$1(无[L]),后面又有一条RewriteRule ^(.*)$ index.php,会导致/new/xxx再次被第二条捕获 - 正确做法:每条有意终止流程的规则都应带
[L];若需多步处理,用[N]或[C]显式控制,避免依赖默认行为
临时启用调试日志定位路径
Apache 2.4 推荐使用 LogLevel alert rewrite:trace3(写入虚拟主机或主配置),然后重启服务,复现请求后查看 error_log 中的逐行匹配过程。
- 日志会显示每次 URI 变化、条件是否满足、规则是否触发、重写后的新 URI 是什么
- initial URI 和
rewritten URI形成闭环(如/a→/b→/a)










