【问题标题】:NodeJS API POST request not flowing throughNodeJS API POST请求没有通过
【发布时间】:2019-07-07 03:17:46
【问题描述】:

我正在为用户身份验证构建一个基于 Express 的 Node API。我正在使用 mongo 来存储数据。使用邮递员,我通过传入以下对象提交了 /post 请求

{
"username": "abc",
"password": "abc123",
"email": "abc@ghi.com"
}

在 req.body 下。

这是我的 /post 函数在代码中的样子:

//create one user
router.post('/createUser', async (req, res) => {
  if (!req.body.email || !req.body.password || !req.body.username) {
    return res.status(400).send({
      message: "No username/password/email specified"
    });
  }
  const newUser = new User({
    email: req.body.email,
    username: req.body.username,
    password: req.body.password
  });

await User.create(newUser, (err, data) => {
    //res.send(data);
    if(err) {
      console.log(err);
      res.status(500).send('Error creating user');
    }
  });
});

User.create() 方法在后台调用 .save() 方法。我有保存加密密码的先决条件。在运行帖子时,我收到一条错误消息,上面写着UnhandledPromiseRejectionWarning: Error: data and salt arguments required

我做了一些控制台日志记录并注意到这是因为 user.password 以未定义的形式出现。所以看起来我的请求没有从邮递员那里得到正确的处理。

编辑: 这是架构:

   const userSchema = new mongoose.Schema({
  id: {
    type: Number
  },
  email: {
    type: String,
    unique: true,
    required: true,
  },
  username: {
    type: String,
    unique: true,
    required: true
  },
  password: {
    type: String,
    required: true
  },
});

userSchema.pre('save', (next) => {
  const user = this;
  console.log(user.password);
  bcrypt.hash(user.password, 10, (err, hash) => {
    if (err) {
      next(err);
    } else {
      user.password = hash;
      next();
    }
  });
});

有人可以帮我理解什么问题吗?

【问题讨论】:

  • 你能分享你的架构吗?
  • 您能分享一下您的create() 方法和schema 定义吗?
  • 你能展示你的预钩吗?
  • 我已将架构定义添加到问题中
  • 您能否重写您的问题,因为问题看起来与 POST 操作本身无关,而是与您在 .pre 操作中调用代码的方式有关。

标签: javascript node.js mongodb express mongoose


【解决方案1】:

你不能在 .pre 钩子中使用箭头函数,因为箭头函数不绑定“this”。 “this”应该是指将要保存的每个单独的用户。但是,如果您在箭头函数中使用“this”,它将指向全局对象。运行此代码 console.log(this) 你会看到。将箭头函数用于独立函数。在您的情况下,您正在创建一个对象的一部分的方法,因此您应该避免使用箭头函数

我不使用 .pre,因为一些 mongoose 查询绕过了 mongoose 中间件,所以你需要做额外的工作。所以我改为在路由器内对密码进行哈希处理,因此与用户相关的所有内容都将在同一个地方。单一事实来源

const bcrypt = require("bcrypt");
router.post('/createUser', async (req, res) => {
  if (!req.body.email || !req.body.password || !req.body.username) {
    return res.status(400).send({
      message: "No username/password/email specified"
    });
  }
  const newUser = new User({
    email: req.body.email,
    username: req.body.username,
    password: req.body.password
  });
//we created newUser and now we have to hash the password
  const salt = await bcrypt.genSalt(10);
  newUser.password = await bcrypt.hash(newUser.password, salt);
  await newUser.save();
  res.status(201).send(newUser)
  //201 code success for something is created
});

这里是http状态码列表:

https://httpstatuses.com/

【讨论】:

  • 这肯定是我想要的。它现在按预期工作。但是,我很好奇为什么当我们基本上在做相同的过程时 pre hook 不起作用
【解决方案2】:

您的 NodeJS 代码已收到来自邮递员的密码。

在您的代码中:

const newUser = new User({
    email: req.body.email,
    username: req.body.username,
    password: req.body.password
  });

当您这样做时,您预期的 newUser 输出会发生变化。

所以当你的代码到达这里时...

  const user = this;
  console.log(user.password);

而不是记录 user.password 尝试记录用户本身...

console.log(user)

看看有没有 "(const user=this)" 是你所期望的。

【讨论】:

  • 我试过了,它返回为未定义。我知道它可能缺少我在问题中提到的 req.body 参数。但我无法理解为什么会这样。
【解决方案3】:
signUp: (req, res, next) => {
    bcrypt.genSalt(10, (err, salt) => {
        bcrypt.hash(req.body.password, salt, (err, hashedPass) => {
            let insertquery = {
                '_id': new mongoose.Types.ObjectId(),
                'username': req.body.username,
                'email': req.body.password,
                'salt': salt,
                'password': hashedPass
            };
            user.create(insertquery, function (err, item) {
            });
        });
    });
}

【讨论】:

    猜你喜欢
    • 2015-11-03
    • 1970-01-01
    • 1970-01-01
    • 2018-05-04
    • 2018-11-26
    • 2016-12-15
    • 1970-01-01
    • 2021-05-27
    • 1970-01-01
    相关资源
    最近更新 更多