跨域预检被拒,GET 能过 POST 不行
查询瓦片正常,一提交分析任务就报跨域;网络面板里多出一条 OPTIONS 请求,返回 405。
现象
浏览器控制台:
Access to fetch at 'https://gis.example.cn/geoserver/rest/process' from origin
'https://app.example.cn' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
网络面板中 OPTIONS /geoserver/rest/process 返回 405 Method Not Allowed,
Allow 响应头里只有 GET, HEAD, POST。
原因
带自定义头(如 Content-Type: application/json、Authorization)
或非简单方法的请求,浏览器会先发 OPTIONS 预检。
预检请求不带凭证,也不会命中后端的业务路由,很多框架直接返回 405。
另一个常见错误是同时写 Access-Control-Allow-Origin: *
与 Access-Control-Allow-Credentials: true,
浏览器会判定为非法组合并拒绝。
排查过程
- 网络面板筛选
OPTIONS,确认状态码与响应头。 - 看请求是否带
withCredentials或自定义头,决定是否真的需要预检。 - 用
curl手动发一次预检,排除浏览器缓存干扰。
curl -i -X OPTIONS "https://gis.example.cn/geoserver/rest/process" \
-H "Origin: https://app.example.cn" \
-H "Access-Control-Request-Method: POST" \
-H "Access-Control-Request-Headers: content-type,authorization"
解决方案
在 Nginx 层统一处理预检,后端不必关心 OPTIONS。注意 always
让 4xx 响应也带上跨域头:
location /geoserver/ {
if ($request_method = OPTIONS) {
add_header Access-Control-Allow-Origin "https://app.example.cn" always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
add_header Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With" always;
add_header Access-Control-Max-Age 86400 always;
add_header Content-Length 0;
return 204;
}
add_header Access-Control-Allow-Origin "https://app.example.cn" always;
add_header Access-Control-Allow-Credentials "true" always;
add_header Access-Control-Expose-Headers "Content-Length, Content-Range" always;
proxy_pass http://127.0.0.1:8080/geoserver/;
}
需要允许任意来源时,就不能带凭证。二者只能选一个:
# 允许任意来源,但不允许携带 Cookie
add_header Access-Control-Allow-Origin "*" always;
add_header Access-Control-Allow-Credentials "false" always;
前端确实不需要凭证时,去掉 credentials: 'include',
请求会从“预检 + 实际请求”两次变成一次:
fetch('https://gis.example.cn/geoserver/rest/process', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
验证
预检请求返回 204,响应头包含 Access-Control-Allow-Origin
与 Access-Control-Allow-Methods。
浏览器控制台不再出现 CORS 报错,POST 请求正常返回结果。
带 Cookie 的请求与不带 Cookie 的请求分别测试,均通过。
先看预检:GET 能过、POST 不能过,几乎都是预检没通过。 CORS 报错文案里的 “preflight request” 是判断依据,不必去查后端业务逻辑。
经纬志(2026)。《跨域预检被拒,GET 能过 POST 不行》。https://www.jingweizhi.com/cookbook/wms-cors-preflight.html(访问日期 2026-11-03)。