使用GraphQL Shield搭配Apollo GraphQL执行mutation出现CORS错误如何解决
排查与解决步骤
1 先确认是否为真CORS错误
绝大多数情况下引入GraphQL Shield后出现的跨域报错都是假CORS错误:Shield权限校验触发4xx/5xx报错时,响应未携带CORS头,浏览器就会将响应拦截并提示跨域。你可以先打开浏览器开发者工具的「网络」面板,找到对应的GraphQL请求,查看实际响应状态码和响应头是否包含Access-Control-Allow-Origin字段,优先排除Shield规则报错的问题。
2 调整CORS配置优先级
你当前配置的全局cors()中间件对Apollo服务默认不生效,Apollo Server会单独处理/graphql路径的CORS配置,优先级高于全局中间件,需要按你使用的集成方式显式配置:
- 如果你用的是
applyMiddleware方式集成:
server.applyMiddleware({ app, // 按需配置允许的源,测试阶段可以先设为* cors: { origin: "*", credentials: true } })
- 如果你用的是Apollo 4+的
startStandaloneServer方式集成:
const { url } = await startStandaloneServer(server, { listen: { port: 4000 }, cors: { origin: "*", credentials: true } })
同时需要确保cors()中间件的注册顺序在所有其他路由/中间件之前,避免OPTIONS预检请求被Shield/Apollo提前拦截:
const app = express() // 第一行就注册cors中间件 app.use(cors()) // 再注册其余中间件、Apollo服务等
3 排查GraphQL Shield规则问题
先临时配置全允许的Shield规则,验证是否是权限规则触发的报错:
import { shield, allow } from 'graphql-shield' const permissions = shield({ Query: allow, Mutation: allow })
如果修改后跨域报错消失,说明是你原有Shield的权限规则校验不通过导致报错,按需调整规则即可。
另外如果开启了Shield的debug: true配置,也可能因为抛出完整堆栈信息破坏响应结构,导致CORS头丢失,可以先关闭debug模式测试。
4 兜底强制附加CORS头
如果上面的配置都不生效,可以添加全局中间件强制给所有响应附加CORS头:
app.use((req, res, next) => { res.header('Access-Control-Allow-Origin', '*') res.header('Access-Control-Allow-Methods', 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS') res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization') if (req.method === 'OPTIONS') return res.sendStatus(200) next() })
内容的提问来源于stack exchange,提问作者elad
相关产品推荐
相关产品推荐

