Apache2 mod_rewrite中L标记未终止重写的问题咨询
Apache RewriteRule中L标记未终止重写的原因
配置与问题现象
你在虚拟主机中配置的重写规则如下:
RewriteEngine On RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d # handles landing page RewriteRule ^/?$ index.php [L] RewriteRule ^(.+)$ post.php?clean_url=$1 [L,QSA]
访问http://192.168.1.120时,URL被意外重写为不存在的http://192.168.1.120/post.php?clean_url=index.php。明明第一条规则已将根路径改写为index.php且带有[L]标记,却没有终止重写流程,第二条规则依然生效。你的Apache版本为:Apache/2.4.52 (Ubuntu)。
原因解析
[L]标记的行为差异
在服务器/虚拟主机配置上下文里,[L]标记不会直接终止整个重写流程,而是触发内部重定向——Apache会以重写后的URI重新发起一次请求处理。这和.htaccess文件中的行为不同,后者里的[L]会终止当前轮次的重写。RewriteCond的作用范围限制
你配置里的两个RewriteCond仅对紧随其后的第一条RewriteRule生效,第二条规则没有任何前置条件限制,只要请求URI匹配^(.+)$(任意非空字符串)就会执行。具体执行流程
- 访问根路径时,请求URI为
/,匹配第一条规则,被重写为index.php,触发内部重定向; - 内部重定向后,新的请求URI变为
/index.php,再次进入重写引擎; - 此时第一条规则不再匹配(URI不是空路径),但第二条规则的
^(.+)$完全匹配index.php,因此被重写为post.php?clean_url=index.php。
修复方案
方案一:给第二条规则添加相同的条件限制
确保仅当请求的文件或目录不存在时,才执行第二条规则:
RewriteEngine On RewriteBase / # 处理首页 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^/?$ index.php [L] # 处理其他路径 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.+)$ post.php?clean_url=$1 [L,QSA]
方案二:调整规则匹配逻辑,避免二次匹配
通过正则排除index.php,确保第二条规则不会匹配内部重定向后的URI:
RewriteEngine On RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d # 先处理非首页的路径,排除index.php RewriteRule ^(?!index\.php$)(.+)$ post.php?clean_url=$1 [L,QSA] # 再处理首页 RewriteRule ^/?$ index.php [L]
内容的提问来源于stack exchange,提问作者sofname
相关产品推荐
相关产品推荐

