Heroku部署React客户端报CORS预检请求未通过访问控制检查如何解决
问题原因排查
- 中间件加载顺序错误:如果当前CORS配置写在路由定义、静态资源处理或其他请求中间件之后,OPTIONS预检请求会被前面的逻辑直接拦截返回,不会走到CORS中间件生成跨域头,就会触发该报错。
- Heroku反向代理干扰:Heroku部署时会在Node服务前增加一层反向代理,部分场景下会修改请求的origin头,导致CORS白名单匹配失败,不会返回
Access-Control-Allow-Origin头。 - 预检请求未单独配置:如果请求带自定义头、使用非简单请求方法(如PUT、DELETE)或
Content-Type: application/json,需要服务端单独响应OPTIONS类型的预检请求,否则也会校验失败。 - 语法规范问题:配置里的origin数组混用了单引号和双引号,部分严格的Node版本或编译环境下可能触发解析异常,导致CORS配置不生效。
解决方案
- 调整中间件加载顺序,把CORS配置放在所有路由、其他中间件的最上方:
// 必须放在所有app.use、路由定义的最前面 const cors = require('cors'); app.use( cors({ credentials: true, origin: [ 'https://sephora-admin.herokuapp.com', 'https://sephora-client-app.herokuapp.com', 'http://localhost:3000', 'http://localhost:3001', ], }) ); // 后续再写其他中间件、路由逻辑
- 新增全局预检请求处理逻辑,在CORS配置后添加:
app.options('*', cors());
- 开启代理信任适配Heroku环境,在CORS配置前添加:
app.set('trust proxy', 1);
- 若仍不生效可替换为动态origin校验逻辑,避免白名单匹配失败:
app.use( cors({ credentials: true, origin: (origin, callback) => { const allowList = [ 'https://sephora-admin.herokuapp.com', 'https://sephora-client-app.herokuapp.com', 'http://localhost:3000', 'http://localhost:3001', ]; // 允许白名单内的源,以及无origin的本地测试请求 if(allowList.includes(origin) || !origin) { callback(null, true); } else { callback(new Error('Not allowed by CORS')); } }, }) );
- 部署完成后可用curl命令直接校验预检请求返回头是否正确:
curl -I -X OPTIONS -H "Origin: https://sephora-admin.herokuapp.com" -H "Access-Control-Request-Method: GET" https://sephora-api-demo.herokuapp.com/api/admin/admin-product/product-properties
正常返回结果中应包含access-control-allow-origin: https://sephora-admin.herokuapp.com响应头。
内容的提问来源于stack exchange,提问作者Sang
相关产品推荐
相关产品推荐

