本地Docker容器API跨域请求CORS预检重定向问题排查
解决跨域请求中CORS预检请求重定向的错误
我刚碰到过类似的问题,咱们一步步来排查和解决:
问题根源分析
你遇到的错误核心是浏览器发送的OPTIONS预检请求被服务器重定向了,而CORS策略不允许预检请求有重定向行为。结合你的配置来看,可能的触发原因有两个:
- 你的
.htaccess里开启了+Indexes,如果api/cache/clear-all恰好是一个实际存在的目录,服务器会自动把不带斜杠的请求重定向到带斜杠的版本(比如/api/cache/clear-all→/api/cache/clear-all/) - 即使不是目录,请求在经过Rewrite规则处理时,也可能因为URL格式触发隐式重定向,而OPTIONS请求在到达你的
index.php之前就被重定向了,导致重定向响应里没有你设置的CORS头,浏览器直接报错。
具体解决方案
1. 在.htaccess中优先处理OPTIONS预检请求
直接在.htaccess最顶部添加规则,拦截OPTIONS请求并返回正确的CORS头,避免它进入后续的Rewrite流程:
# 先处理OPTIONS预检请求,直接返回200和CORS头 RewriteEngine On RewriteCond %{REQUEST_METHOD} OPTIONS RewriteRule ^(.*)$ $1 [R=200,L,E=HTTP_ORIGIN:%{HTTP:ORIGIN}] # 全局设置CORS响应头 Header always set Access-Control-Allow-Origin "*" Header always set Access-Control-Allow-Methods "GET, POST, PATCH, PUT, DELETE, OPTIONS" Header always set Access-Control-Allow-Headers "Origin, Content-Type, X-Auth-Token, X-Requested-With" # 保留你原有的Rewrite规则 RewriteBase /api RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php?request=$1 [QSA,NC,L] Options All +Indexes allow from all
注意:要确保你的Apache服务器启用了
mod_headers模块,否则Header指令会失效。Linux环境下可以用a2enmod headers命令启用。
2. 修复请求URL的斜杠问题
从你的XHR详情看到,实际请求的URL是http://websites.click/api/cache/clear-all/(末尾多了斜杠),但你的Axios代码里写的是不带斜杠的。这种不一致很容易触发服务器的自动重定向,你可以:
- 检查
api/cache/clear-all是否是实际存在的目录,如果是,要么删除这个目录,要么在Axios请求里统一加上末尾斜杠 - 修改Axios请求的URL,明确保持格式一致:
window.axios.get('//websites.click/api/cache/clear-all', { }) .then(response => { console.log(response); })
3. 验证index.php的CORS头设置
虽然我们在.htaccess里处理了OPTIONS请求,但实际的GET请求还是会走到index.php,所以你原来设置的CORS头可以保留,但要确保在输出任何内容之前就发送这些头(比如不要在echo、print等输出之后才加header),避免出现"headers already sent"的错误。
为什么这样能解决问题?
通过在.htaccess里直接处理OPTIONS请求,我们让浏览器的预检请求直接得到带CORS头的200响应,不会进入后续的Rewrite或重定向流程,从根源上避免了"预检请求不允许重定向"的错误。同时统一URL格式,也能减少不必要的重定向触发。
内容的提问来源于stack exchange,提问作者Martyn Ball




