ExpressJS:发送后不能设置标头

时间:2018-02-07 07:48:22

标签: node.js express passport.js

我在ExpressJS中有一个API。在该API中,我有一个登录端点,当发布到该端点时,我不断得到在发送后无法设置标头的异常。

我知道这通常是一个回调,被调用两次或者没有从具有设置标题的东西正确返回,导致应用尝试再次设置它们,但是在我的/login端点我不这样做

我无法理解为什么会发生这种情况,我希望得到一些意见,因为我接近将我的头发拉出来阅读相同的回复和答案。我希望这是我遗漏的明显事实。

import User from '../../models/user';
import { Router } from 'express';
import jwt from 'jsonwebtoken';

export default () => {
  const route = Router();

  route.post('/create', async (req, res, next) => {
    if (!req.body.email || !req.body.password) {
      return res
        .status(400)
        .json({ message: 'username or password is missing' });
    }

    const { email, password } = req.body;
    const count = await User.count({ email });

    if (count > 0) {
      return res.status(409).json({ message: 'email must be unique' });
    }

    const newUser = await new User({ email, password });
    const doc = await newUser.save();

    return res.status(201).json({ type: 'account', attributes: doc });
  });

  route.post('/login', async (req, res, next) => {
    if (req.body.email && req.body.password) {
      const { email, password } = req.body;

      const user = await User.findOne({ email });
      if (user) {
        user.comparePassword(password, isMatch => {
          if (isMatch) {
            const token = jwt.sign(
              { sub: user.id, roles: [], email: user.email },
              process.env.SECRET_KEY,
              { expiresIn: '12h' },
            );

            return res
              .status(200)
              .json({ type: 'account', attributes: { token } });
          }
        });
      }
    }
    res.sendStatus(401);
  });

  return route;
};

3 个答案:

答案 0 :(得分:0)

这里的问题。 comparePassword中的回调仅在该回调内返回。所以代码仍然运行到res.sendStatus(401),在回调完成后,它将运行res.status(200).json...

user.comparePassword(password, isMatch => {
              if (isMatch) {
                const token = jwt.sign(
                  { sub: user.id, roles: [], email: user.email },
                  process.env.SECRET_KEY,
                  { expiresIn: '12h' },
                );

                return res
                  .status(200)
                  .json({ type: 'account', attributes: { token } });
              }
            });

答案 1 :(得分:0)

尝试在用户模型中宣传comparePassword方法:

userSchema.methods.comparePassword = function (password) {

    return new Promise( function(resolve, reject) {
        resolve(password === this.password);
    });

}

现在您可以使用await语法来获取承诺结果:

route.post('/login', async (req, res, next) => {
    if (req.body.email && req.body.password) {
        const { email, password } = req.body;

        const user = await User.findOne({ email });

        if (user) {

            const isMatch = await user.comparePassword(password);

            if (isMatch) {
                const token = jwt.sign(
                    { sub: user.id, roles: [], email: user.email },
                    process.env.SECRET_KEY,
                    { expiresIn: '12h' },
                );

                return res
                    .status(200)
                    .json({ type: 'account', attributes: { token } });
            }
        }
    }
    res.sendStatus(401);
});

答案 2 :(得分:0)

import User from '../../models/user';
import { Router } from 'express';
import jwt from 'jsonwebtoken';

export default () => {
  const route = Router();

  route.post('/create', async (req, res, next) => {
    if (!req.body.email || !req.body.password) {
      return res
        .status(400)
        .json({ message: 'username or password is missing' });
    }

    const { email, password } = req.body;
    const count = await User.count({ email });

    if (count > 0) {
      return res.status(409).json({ message: 'email must be unique' });
    }

    const newUser = await new User({ email, password });
    const doc = await newUser.save();

    return res.status(201).json({ type: 'account', attributes: doc });
  });

  route.post('/login', async (req, res, next) => {
    if (req.body.email && req.body.password) {
      const { email, password } = req.body;

      const user = await User.findOne({ email });
      if (user) {
        return user.comparePassword(password, isMatch => {
          if (isMatch) {
            const token = jwt.sign(
              { sub: user.id, roles: [], email: user.email },
              process.env.SECRET_KEY,
              { expiresIn: '12h' },
            );

            return res
              .status(200)
              .json({ type: 'account', attributes: { token } });
          } else {
             return res.status(400)
               .json({ message: 'username or password is invalid' });
           }
        });
      }
    }
    res.sendStatus(401);
  });

  return route;
};

查看

中缺少的更新代码返回

return user.comparePassword(password, isMatch => {

希望它能解决你的问题。