Apache mod_rewrite存在同名目录时请求方法变为GET如何修复?
问题根源
Apache默认开启的mod_dir模块DirectorySlash功能导致的:当请求路径对应一个真实存在的目录且路径末尾未携带斜杠时,Apache会自动返回301/302重定向到末尾加斜杠的同路径,这个重定向过程会自动将OPTIONS、POST等非GET/HEAD请求的方法转换为GET,同时丢失原始请求的所有载荷。
修复方案
第一步:关闭DirectorySlash自动补全斜杠功能
在你的.htaccess文件最顶部添加一行配置:
DirectorySlash Off
第二步:修正现有重写规则的逻辑错误
你当前的重写条件逻辑冗余:RewriteCond %{REQUEST_FILENAME} -f [OR]和RewriteCond %{REQUEST_FILENAME} !-f是互斥条件加OR,等于所有请求都会触发重写,没有实际判断意义,可以根据你的业务需求调整:
- 若要求所有请求(包括真实存在的文件、目录请求)全部转发到index.php,直接删除两条重写条件即可,最终完整配置如下:
DirectorySlash Off RewriteEngine On # 透传Authorization头 RewriteCond %{HTTP:Authorization} ^(.*) RewriteRule .* - [e=HTTP_AUTHORIZATION:%1] # 所有请求全部转发到index.php RewriteRule ^(.*)$ index.php [L,QSA] - 若要求仅当请求的不是真实存在的文件/目录时才转发到index.php,调整重写条件为如下格式即可:
DirectorySlash Off RewriteEngine On # 透传Authorization头 RewriteCond %{HTTP:Authorization} ^(.*) RewriteRule .* - [e=HTTP_AUTHORIZATION:%1] # 仅非真实文件/目录的请求才转发到index.php RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php [L,QSA]
第三步(可选):保留目录访问的斜杠补全逻辑
如果你的业务需要正常访问存在的目录时仍有斜杠补全功能,可以额外添加一条专门处理目录斜杠补全的规则,指定重定向时保留原始请求方法:
# 存在的目录请求自动补全斜杠,重定向时保留原始请求方法 RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^(.*[^/])$ /$1/ [R=308,L]
这里的308状态码表示永久重定向,且不允许修改请求方法,不会出现OPTIONS转GET的问题。
内容的提问来源于stack exchange,提问作者Matthias Thalmann
相关产品推荐
相关产品推荐

