Apache单.htaccess为不同子域名配置重写规则报500错误求助
故障根因
两种配置触发访问index.php返回500错误的核心原因是重写规则死循环:
当请求被重写规则转发到/index.php后,Apache会发起内部重定向,重新从头加载执行.htaccess中的所有规则,此时请求会再次被匹配、再次转发到index.php,循环次数超过Apache默认的10次上限后,就会直接返回500内部服务器错误。
两个配置还分别存在额外问题:
- 第一种
<If>块写法:博客子域名规则组完全没有添加index.php的重写豁免逻辑,且规则中路径匹配带了开头斜杠,不符合.htaccess上下文的RewriteRule匹配规则(.htaccess中匹配的是相对路径,不带前缀斜杠);同时使用的L标记只能终止当前轮次的重写,无法阻止内部重定向触发的新一轮规则执行。 - 第二种环境变量写法:Apache在内部重定向时会给已设置的环境变量加上
REDIRECT_前缀,第二轮规则执行时原有的SUBDOMAIN变量已经变成REDIRECT_SUBDOMAIN,原有变量判断逻辑直接失效,无法正确命中豁免规则,同样触发循环。
排查步骤
- 首先查看主机的Apache错误日志,500错误对应的日志条目会明确标注
Request exceeded the limit of 10 internal redirects due to probable configuration error,可直接确认循环问题。 - 梳理重写执行逻辑:
.htaccess中的重写规则不会只执行一次,每次内部重定向都会从头重新加载所有规则,必须对最终转发到的入口文件(这里是index.php)做重写豁免。 - 校验规则匹配逻辑:确认
.htaccess上下文的RewriteRule路径不要带开头斜杠,环境变量在重定向后的命名变化,以及重写标记的作用范围。
可用修正方案
优先选择第一种<If>块写法,可读性高、后续新增子域名规则时维护成本低,修正后的配置如下:
<IfModule mod_rewrite.c> RewriteEngine On RewriteBase / # 传递HTTP_AUTHORIZATION头 RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] # 主站 example.org 规则 <If "%{HTTP_HOST} == 'example.org'"> # 直接请求index.php时终止所有重写,切断循环 RewriteRule ^index\.php$ - [END] # 仅当请求路径不是真实存在的文件、目录时,才转发到index.php RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [END,QSA] </If> # 博客子域名 blog.example.org 规则 <If "%{HTTP_HOST} == 'blog.example.org'"> # 先加index.php重写豁免 RewriteRule ^index\.php$ - [END] # 作者页规则:/autor/{author name},去掉路径开头的斜杠适配.htaccess上下文 RewriteRule ^autor/([^/]+)/?$ /index.php?author_name=$1 [END,QSA] # 博客首页规则:/{blog name} RewriteRule ^([^/]+)/?$ /index.php?blog=$1 [END,QSA] # 文章详情规则:/{blog name}/{year}/{article name} RewriteRule ^([^/]+)/([0-9]{4})/([^/]+)/?$ /index.php?blog=$1&year=$2&name=$3 [END,QSA] # 子域名根路径规则 RewriteRule ^$ /index.php?post_type=post [END,QSA] </If> </IfModule>
修正点说明
- 所有重写规则的
L标记替换为END标记:END标记会直接终止整个重写流程,不会触发新一轮的内部重定向,从根源上避免循环问题(Apache 2.4及以上版本支持,目前绝大多数虚拟主机都已满足版本要求)。 - 给博客子域名规则组补充了
index.php的豁免规则,避免重写到入口文件后再次匹配转发规则。 - 去掉了博客子域名RewriteRule匹配路径开头的斜杠,适配
.htaccess上下文的匹配逻辑,确保规则能正常命中。 - 所有转发规则加上
QSA标记,保留原请求自带的查询参数,避免参数丢失。
如果使用的主机Apache版本低于2.4不支持<If>和END标记,可以使用修正后的环境变量写法,核心是给环境变量判断加上REDIRECT_前缀,同时给所有转发规则加上!-f/!-d判断,确保不会重复转发真实存在的index.php文件,不过该写法冗余度高,新增子域名时需要同时修改变量设置和规则判断两处,不推荐优先使用。
内容的提问来源于stack exchange,提问作者Gregor
相关产品推荐
相关产品推荐

