Apache .htaccess RewriteRule引发409错误的原因排查求助
问题描述
我配置了以下.htaccess规则:
Options +FollowSymLinks -MultiViews RewriteEngine On RewriteBase / RewriteCond %{HTTPS} off [OR] RewriteCond %{HTTP_HOST} ^www\. [NC] RewriteCond %{HTTP_HOST} ^(www\.)?(.+)$ RewriteRule (.*) https://%2%{REQUEST_URI} [R=301,NE,L] # 301 externally redirect all .php extensioned requests to extensionless RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+)\.php [NC] RewriteRule ^ %1 [R=301,NC,NE,L] RewriteRule ^contact$ /?modal=contact [NC,L] # if x.php is a file, internally add .php to x RewriteCond %{REQUEST_FILENAME}\.php -f RewriteRule !.*\.php$ %{REQUEST_URI}.php [NC,L]
这些规则可将以下任意URL:
http://www.example.com/contact http://www.example.com/contact.php http://example.com/contact http://example.com/contact.php https://www.example.com/contact https://www.example.com/contact.php https://example.com/contact https://example.com/contact.php
重定向至:https://example.com/?modal=contact,同时还能让https://example.com/page内部解析为https://example.com/page.php,实现无后缀访问。
但请求如https://www.example.com/contact.php时,虽浏览器显示预期结果,却出现409错误。相关情况:
- 在Google Search Console和wheregoes.com中可见409错误
- Chrome DevTools仅显示两次301状态
- 服务器原始访问日志显示301前存在409,但不清楚原因
请求https://example.com/contact.php的服务器日志如下:
IP.AD.RE.SS - - [22/Sep/2022:10:27:31 -0500] "GET /contact.php HTTP/2.0" 409 83 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36" example.com IP.AD.RE.SS2 IP.AD.RE.SS - - [22/Sep/2022:10:27:31 -0500] "GET /contact.php HTTP/2.0" 301 235 "https://example.com/contact.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36" example.com IP.AD.RE.SS2 IP.AD.RE.SS - - [22/Sep/2022:10:27:31 -0500] "GET /contact HTTP/2.0" 301 246 "https://example.com/contact.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36" example.com IP.AD.RE.SS2 IP.AD.RE.SS - - [22/Sep/2022:10:27:31 -0500] "GET /?modal=contact HTTP/2.0" 200 5242 "https://example.com/contact.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36" example.com IP.AD.RE.SS2
请问该409错误的成因是什么?
409错误成因分析
409冲突错误的核心原因是重写规则与资源状态的执行冲突,具体细节如下:
- 当服务器接收到
/contact.php请求时,会同时进行两个操作:一是匹配第二条重写规则,准备将请求重定向到无后缀的/contact;二是验证contact.php文件的存在状态。 - 由于第三条规则对
/contact设置了强制跳转到/?modal=contact的规则,服务器在处理过程中,将"存在可直接访问的contact.php文件"与"对应无后缀路径需强制跳转至其他资源"的情况判定为资源状态冲突——相当于同一资源入口存在两种不同的处理逻辑,服务器无法确定优先执行哪一个,因此返回409错误。 - 客户端重试请求时,服务器会优先执行已匹配的重定向规则链(
contact.php→contact→/?modal=contact),跳过了文件状态的验证环节,因此正常返回301重定向,最终完成整个流程得到200响应。
从日志的四次请求流程也能佐证这一点:第一次请求触发了服务器的资源冲突检测,返回409;重试后服务器直接走重定向规则,流程正常完成。
内容的提问来源于stack exchange,提问作者chillywilly
相关产品推荐
相关产品推荐

