Fetch API预检请求跨域错误求助:Postman及浏览器可访问endpoint
嘿,这问题我见得不少,典型的CORS预检请求失败问题,我来给你理清楚前因后果和解决办法:
问题原因拆解
为什么Postman和直接浏览器访问正常?
这俩场景根本不会触发浏览器的CORS限制:
- 直接在浏览器地址栏输入URL属于导航请求,是浏览器本身的行为,不受同源策略的CORS规则约束;
- Postman作为API测试工具,默认不会发送CORS相关的预检请求,也不会校验响应里的CORS头,自然能正常拿到返回结果。
为什么Fetch会触发预检请求并失败?
当你的Fetch请求满足以下任意条件时,浏览器会自动帮你发起一个OPTIONS预检请求,用来提前确认服务器是否允许当前域名的跨域请求:
- 请求方法不是GET/HEAD/POST;
- POST请求的Content-Type不是
application/x-www-form-urlencoded、multipart/form-data或text/plain; - 请求包含自定义的HTTP头(比如Authorization、X-Requested-With这类)。
如果服务器没有正确响应这个OPTIONS请求(比如没返回必要的CORS头,或者直接返回404/错误状态码),浏览器就会拦截后续的实际请求,抛出你看到的preflight request doesn't pass access control check错误。
解决方案
前端侧临时调整(仅限排查或特殊场景)
如果只是临时测试,你可以先检查并调整Fetch请求的配置:
- 确保请求方法是GET/HEAD/POST,且POST请求的Content-Type是上述允许的类型;
- 移除不必要的自定义请求头;
- 尝试添加
mode: 'no-cors'配置,但注意这样你无法读取响应内容,只能拿到一个无法解析的opaque响应,适合只需要触发请求但不需要处理结果的场景,不推荐作为长期方案:fetch('your-internal-endpoint', { mode: 'no-cors' // 其他配置... })
后端侧核心修复(必须步骤)
这个问题的根源在服务器配置,需要联系公司的后端/运维团队调整CORS规则:
- 确保服务器能正确处理OPTIONS预检请求,返回200状态码;
- 在响应中添加必要的CORS头:
Access-Control-Allow-Origin: 设置为你的前端域名(比如https://your-frontend-domain.com),生产环境别用*,不安全;Access-Control-Allow-Methods: 列出允许的请求方法(比如GET, POST, OPTIONS);Access-Control-Allow-Headers: 如果你的请求用了自定义头,这里要列出对应的头名称;Access-Control-Max-Age: 设置预检请求的缓存时间(比如86400,也就是24小时),避免每次请求都发OPTIONS。
举个Node.js/Express环境下的配置示例:
// 处理所有OPTIONS请求 app.options('*', (req, res) => { res.setHeader('Access-Control-Allow-Origin', 'https://your-frontend-domain.com'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization'); res.setHeader('Access-Control-Max-Age', 86400); // 缓存24小时 res.sendStatus(200); });
另外,因为是公司内部接口,可能还要确认是否有内部的网关/反向代理需要同步配置跨域规则,有些公司会用域名白名单机制,得确保你的前端域名在允许列表里。
内容的提问来源于stack exchange,提问作者Aaron Balthaser




