Apollo GraphQL Gateway预检请求未通过CORS校验问题排查求助
问题根本原因
- 网关侧中间件顺序错误:你当前的CORS处理逻辑(TRY1、TRY2的cors中间件、手动加响应头)放在了auth校验中间件、路由注册逻辑之后,浏览器发送的OPTIONS预检请求不会携带身份认证信息,走到auth中间件就被拦截返回,根本没有触发你写的CORS处理逻辑,所以后端无请求日志、也没有返回正确的CORS响应头。
- 前后端CORS配置冲突:你同时开启了express全局cors中间件、手动设置响应头、ApolloServer自带cors配置三类处理逻辑,多套规则冲突反而会导致响应头异常。另外你配置了
credentials: true的同时把origin设为*,不符合CORS规范:允许携带凭证的请求不允许使用通配符*作为允许的源。 - 前端配置错误:你在ApolloClient里加了
mode: 'no-cors'的配置,这个模式下浏览器会限制请求不能带自定义头(比如你用到的Authorization头),而且就算后端返回了正确的CORS头,浏览器也会直接拦截响应。
修复方案
后端(GraphQL网关)修复
- 调整中间件顺序,把CORS相关逻辑放到所有auth校验、路由注册的最前面,示例调整后的代码顺序:
const app = express(); // 第一步:最先处理CORS const corsOptions = { origin: ['http://localhost:3000', 'https://stage-tool.mydomain.net', 'https://stage.tool.mydomain.net', 'https://dsr.mydomain.net'], credentials: true, allowedHeaders: ['Origin', 'X-Requested-With', 'Content-Type', 'Accept', 'Authorization'], methods: ['GET', 'POST', 'OPTIONS'], optionsSuccessStatus: 204 }; app.use(cors(corsOptions)); // 第二步:OPTIONS请求直接返回 app.options('*', cors(corsOptions)); // 第三步:再加载其他中间件、路由、auth校验 app.use(express.static('assets')); // ... 其他原有中间件、路由注册、auth0AuthenticationCheck等逻辑 ...
- 删掉TRY2的手动设置响应头代码,避免和cors中间件冲突。
- 保持ApolloServer的
cors: false配置即可,不需要再用Apollo自带的CORS处理。
前端修复
直接删掉ApolloClient配置中的fetchOptions: { mode: 'no-cors' }配置项即可。
排查思路
- 优先用curl直接发送OPTIONS请求到网关地址,验证后端配置是否生效:
curl -X OPTIONS http://dev.gateway.mydomain.net:5000/graphql \ -H "Origin: http://localhost:3000" \ -H "Access-Control-Request-Method: POST" \ -H "Access-Control-Request-Headers: content-type,authorization" \ -I
如果返回的响应头中没有Access-Control-Allow-Origin等相关字段,优先排查后端中间件顺序和CORS配置。
2. 后端验证通过后再测试前端请求,此时如果仍有报错,直接对比浏览器控制台预检请求的Access-Control-Request-*字段,把缺失的请求头、请求方法加到后端CORS配置的允许列表中即可。
内容的提问来源于stack exchange,提问作者zabumba
相关产品推荐
相关产品推荐

