使用猫鼬和Joi在Express HTTP API中一致的错误验证响应

时间:2019-02-07 16:36:27

标签: node.js express mongoose joi

由于我来自前端,因此我对Node后端开发非常陌生。 我正在开发使用Express,Mongo,Mongoose和Joi进行输入验证的http api。

我同时使用MongooseJoi模式验证,后者仅在特定情况下使用,例如发布/发布/补丁路由。

在猫鼬模式中为电子邮件字段使用“唯一”规则,我偶然发现了以下问题:猫鼬的错误响应与Joi的响应有很大不同。您可以想象,应该首选一致的响应,以避免前端进行复杂的数据解析以显示UI中的错误。

这是针对唯一电子邮件的猫鼬错误响应的示例:

{
  "errors": {
  "email": {
    "message": "Error, expected 'email' to be unique. Value: 'lorem.ipsum@yahoo.com'",
    "name": "ValidatorError",
    "properties": {
      "message": "Error, expected 'email' to be unique. Value: 'lorem.ipsum@yahoo.com'",
      "type": "unique",
      "path": "email",
      "value": "lorem.ipsum@yahoo.com"
    },
    "kind": "unique",
    "path": "email",
    "value": "lorem.ipsum@yahoo.com"
    }
  },
  "_message": "Author validation failed",
  "message": "Author validation failed: email: Error, expected 'email' to be unique. Value: 'lorem.ipsum@yahoo.com'",
  "name": "ValidationError"
}

这是Joi错误密码响应的示例:

{
  "isJoi": true,
  "name": "ValidationError",
  "details": [
    {
      "message": "\"password\" with value \"3\" fails to match the required pattern: /^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,32}$/",
      "path": [
        "password"
      ],
      "type": "string.regex.base",
      "context": {
        "pattern": {},
        "value": "3",
        "key": "password",
        "label": "password"
      }
    }
  ],
  "_object": {
    "username": "thequickbrownfox",
    "first_name": "The Quick",
    "last_name": "Brown Fox",
    "email": "thequickbrownfox@hotmail.com",
    "password": "3"
  }
}

请注意,我还使用Mongoose Unique Validator来获取Mongoose唯一的错误消息,而不是默认的E11000 Mongo错误,这是非常无语的。 有没有办法在类似用例中获得类似的错误响应?谢谢。

1 个答案:

答案 0 :(得分:0)

我将从构建用于express的中间件错误处理程序开始,该处理程序捕获来自Mongoose和Joi的不同错误响应,并将它们转换为适合您的统一错误响应。

例如,在您的主Express应用中:

app.use(function (err, req, res, next) {
    if (err) {
        let transformedErrorPayload = parseError(err)
        res.status(someErrorCode).json(transformedErrorPayload)
    }
})

您的变换可能看起来像这样:

parseError(err) {
    if ("isJoi" in err && err.isJoi == true) {
        // do stuff with the Joi error
        return transformedErrorPayload
    } else if ("errors" in err && err.errors instanceof Object) {
        // do stuff with Mongoose error
        return transformedErrorPayload
    }
}