GraphQL突变“将标头发送到客户端后无法设置标头”

时间:2019-12-07 01:00:55

标签: graphql response-headers express-graphql graphql-mutation

我正在实现graphql登录突变以认证用户登录凭据。突变会使用bcrypt验证密码,然后将cookie发送给客户端,客户端将根据cookie是买方还是所有者用户来呈现用户个人资料。

GraphQL登录突变代码:

const Mutation = new GraphQLObjectType({
    name: 'Mutation',
    fields: {
    loginUser: {
            type: UserType,
            args: {
                email: { type: GraphQLString },
                password: { type: GraphQLString }
            },
            resolve: function (parent, args, { req, res }) {
                User.findOne({ email: args.email }, (err, user) => {
                    if (user) {
                        bcrypt.compare(args.password, user.password).then(isMatch => {
                            if (isMatch) {
                                if (!user.owner) {
                                    res.cookie('cookie', "buyer", { maxAge: 900000, httpOnly: false, path: '/' });
                                } else {
                                    res.cookie('cookie', "owner", { maxAge: 900000, httpOnly: false, path: '/' });
                                }
                                return res.status(200).json('Successful login');
                            } else {
                                console.log('Incorrect password');
                            }
                        });
                    }
                });
            }
        }
     }
});

Server.js:

app.use("/graphql",
  (req, res) => {
    return graphqlHTTP({
      schema,
      graphiql: true,
      context: { req, res },
    })(req, res);
  });

错误消息:

(node:10630) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
[0]     at ServerResponse.setHeader (_http_outgoing.js:470:11)
[0]     at ServerResponse.header (/Users/xxx/xxx/server/node_modules/express/lib/response.js:771:10)
[0]     at ServerResponse.append (/Users/xxx/xxx/server/node_modules/express/lib/response.js:732:15)
[0]     at ServerResponse.res.cookie (/Users/xxx/xxx/server/node_modules/express/lib/response.js:857:8)
[0]     at bcrypt.compare.then.isMatch (/Users/xxx/xxx/server/schema/schema.js:89:41)

我已经对此错误进行了一些研究,但似乎找不到相关的答案。问题似乎在于响应主体执行了不止一次,因此“在将标头发送给客户端后无法设置标头”。由于我同时发送了res.cookie()和res.status(200),如何解决此问题?

1 个答案:

答案 0 :(得分:1)

GET /stock/chart/GOOG 304 5.002 ms - - GET /JS/chart.js 304 0.296 ms - - GET /JS/chartWebSearch.js 304 0.451 ms - - on entry req.parms.symbol: GOOG string req.params.symbol in change: AAPL req.params.symbol in change: MSFT req.params.symbol in change: AAPL GET /stock/app/GOOG 304 741.986 ms - - req.params.symbol in change: MSFT req.params.symbol in change: GOOG req.params.symbol in change: AAPL req.params.symbol in change: MSFT req.params.symbol in change: GOOG req.params.symbol in change: GOOG req.params.symbol in change: GOOG req.params.symbol in change: AAPL req.params.symbol in change: AAPL req.params.symbol in change: AAPL req.params.symbol in change: MSFT req.params.symbol in change: MSFT req.params.symbol in change: MSFT req.params.symbol in change: GOOG req.params.symbol in change: GOOG req.params.symbol in change: AAPL req.params.symbol in change: AAPL req.params.symbol in change: MSFT req.params.symbol in change: MSFT GET /stock/updatedb 304 820.259 ms - - 已经设置了状态并为您发送了响应-无需在解析器中调用express-graphqlres.status

GraphQL始终返回状态200,除非所请求的查询无效,在这种情况下它将返回状态400。如果在执行请求时发生错误,它们将包含在响应中(在res.json中数组与返回的errors分开),但状态仍为200。这都是设计使然-请参阅其他讨论here

您的解析器应该返回适​​当类型的值(在这种情况下为data),而不是调用res.json,或者返回一个可以解决该值的Promise。

此外,您不应在解析器内部使用回调,因为它们与Promises不兼容。如果您使用的bcrypt库支持使用Promises,请使用适当的API。如果没有,请切换到可以执行此操作的库(例如bcryptjs)或将您的回调包装在Promise中。同理您正在使用的任何ORM。

最后,您的解析器应如下所示:

UserType