You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Axios/Fetch GET请求转为OPTIONS请求返回401跨域报错问题

问题背景

已掌握CORS预检请求相关机制,服务端已声明支持OPTIONS方法请求。

问题现象
  • 使用Postman、reqbin等所有在线API测试工具调用目标接口均可正常返回
  • 使用Axios或原生fetch发起GET请求时,浏览器自动触发OPTIONS预检请求,该请求返回401 Unauthorized状态码,请求被浏览器拦截
环境说明
  • 本地开发环境基于localtunnel暴露服务,使用Next.js默认服务端配置
  • 服务端已参照标准Nginx CORS配置指引完成规则配置,配置文件路径为/example.com/conf/nginx/cors.conf
前端复现代码
var myHeaders = new Headers();
myHeaders.append("Access-Token", "token-here");

var requestOptions = {
    method: 'get',
    headers: myHeaders,
    crossDomain: true,
    redirect: 'follow'
};

fetch("https://example.com/x/wp-json/api", requestOptions)
    .then(response => response.text())
    .then(result => console.log(result))
    .catch(error => console.log('error', error));
浏览器控制台报错
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://example.com/xx/wp-json/x/api. (Reason: CORS preflight response did not succeed). Status code: 401.
(Reason: CORS header ‘Access-Control-Allow-Origin’ does not match ‘http://localhost:3000, http://localhost:3000’)
服务端返回的CORS相关响应头
响应头值
access-control-allow-credentialstrue
access-control-allow-headersAuthorization, X-WP-Nonce, Content-Disposition, Content-MD5, Content-Type
access-control-allow-methodsOPTIONS, GET, POST, PUT, PATCH, DELETE
access-control-allow-originhttps://localtunnel-URL.loca.lt
content-typeapplication/json; charset=UTF-8

问题截图

问题根因
  1. OPTIONS预检请求被鉴权逻辑拦截:前端请求携带了自定义头Access-Token,属于会触发CORS预检的场景,当前服务端虽然声明支持OPTIONS方法,但未对OPTIONS请求关闭鉴权校验,OPTIONS请求不会携带业务鉴权凭证,直接被鉴权逻辑拦截返回401,导致预检失败。
  2. Access-Control-Allow-Origin配置错误:当前配置写死的允许源为localtunnel分配的域名,但浏览器实际发起请求的源为http://localhost:3000,同时配置存在重复拼接Origin的问题,返回的允许源值和请求实际源不匹配,被浏览器拦截。
  3. 允许请求头配置缺失:当前Access-Control-Allow-Headers列表未包含前端自定义传递的Access-Token头,即使预检请求返回200,也会因自定义头未被服务端允许被拦截。

注:Postman、reqbin等API测试工具是服务端发起请求,不受浏览器同源策略限制,不会自动发送CORS预检请求,因此调用成功不能代表浏览器侧CORS配置符合要求。

修复方案
  1. 放通OPTIONS请求的鉴权校验:在Nginx配置中针对OPTIONS请求直接返回204无内容状态码,不转发到后端业务服务、不触发鉴权逻辑,参考配置如下:
location / {
    # 单独处理OPTIONS预检请求
    if ($request_method = 'OPTIONS') {
        add_header Access-Control-Allow-Origin $http_origin always;
        add_header Access-Control-Allow-Credentials true always;
        add_header Access-Control-Allow-Methods "OPTIONS, GET, POST, PUT, PATCH, DELETE" always;
        add_header Access-Control-Allow-Headers "Authorization, X-WP-Nonce, Content-Disposition, Content-MD5, Content-Type, Access-Token" always;
        add_header Content-Length 0 always;
        add_header Content-Type text/plain always;
        return 204;
    }
    # 原有反向代理、业务路由配置
}
  1. 修正跨域允许源配置:不要写死固定的localtunnel域名,开发环境直接读取请求头中的Origin值作为Access-Control-Allow-Origin的返回值即可;注意开启Access-Control-Allow-Credentials: true时,不能使用通配符*作为允许源,必须返回具体的源地址,同时排查配置中重复拼接Origin的逻辑,避免出现多个源值拼接的情况。
  2. 补全允许请求头列表:在Access-Control-Allow-Headers配置中新增前端传递的自定义头Access-Token,确保自定义头被服务端认可。

内容的提问来源于stack exchange,提问作者Christian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 20:36:24