GraphQL解析器中req未定义但中间件中存在值(Node.js+Express)
问题根源:GraphQL解析器没拿到请求对象!
兄弟,我一眼就发现问题所在了——你在GraphQL解析器里的参数用错了,而且没把Express的req对象传递到解析器的上下文(context)里。
为什么会出现这个问题?
- 解析器参数顺序不对:express-graphql的解析器函数,第一个参数是查询/突变的
args,第二个才是包含请求对象的context,你直接把req当第一个参数,肯定拿不到值。 - 没配置context传递req:默认情况下,express-graphql不会自动把Express的请求对象传给解析器,得手动在配置里指定。
修复步骤
第一步:修改app.js里的graphqlHttp配置,传递req到context
把你的graphqlHttp配置改成下面这样,添加context选项,把Express的req对象注入进去:
app.use('/graphql', graphqlHttp({ schema: graphQlSchema, rootValue: graphQlResolvers, graphiql: true, // 关键:把req传递给解析器的context context: ({ req }) => ({ req }) }));
第二步:调整GraphQL解析器的参数,从context里拿req
你的fetchPosts解析器要修改参数,从context里获取请求对象,而不是直接用第一个参数:
module.exports = { fetchPosts: async (_, context) => { // 第一个参数是args,这里用_忽略,第二个是context console.log(context.req.isAuth); // 现在就能拿到true了! if(!context.req.isAuth){ throw new Error("Not Authorised to access this feature"); } try{ const userId = context.req.userId; const {following} = await User.findOne({_id: userId}); const postList = new Array; await Promise.all(following.map( async eachUser => { const {createdPosts} = await User.findOne({_id: eachUser}); await Promise.all(createdPosts.map(async eachPost => { const postDetail = await Post.findOne({_id: eachPost}); await postList.push(postDetail); })); })); return {postList}; }catch(err){ throw(err); } }, }
额外小提醒:中间件顺序优化
你当前的中间件顺序是先加载isAuth,再加载CORS中间件,其实CORS中间件应该放在最前面,因为浏览器会先发送OPTIONS预检请求,需要先处理跨域:
// 调整顺序:先处理CORS,再处理认证 app.use((req, res, next)=>{ console.log(req); res.setHeader('Access-Control-Allow-Origin','*'); res.setHeader('Access-Control-Allow-Methods', 'POST,GET,OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type,Authorization'); if (req.method === 'OPTIONS'){ return res.sendStatus(200); } next(); }); app.use(isAuth); // 移到CORS后面
这样改完之后,你的解析器就能正常拿到req.isAuth和req.userId了,应该就能解决问题啦!
内容的提问来源于stack exchange,提问作者Captain
相关产品推荐
相关产品推荐

