Express http api 中一致的错误验证响应,使用 mongoose 和 Joi

Consistent error validation responses in Express http api, using mongoose and Joi

我是 Node 后端开发的新手,因为我来自前端。 我正在使用 Express、Mongo、Mongoose 和 Joi 开发一个 http api 来进行输入验证。

我同时使用 Mongoose and Joi 模式验证,后者仅在特定情况下使用,例如 post/put/patch 路由。

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

中显示错误

这是Mongo针对唯一电子邮件设置错误响应的示例:

{
  "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 错误,这是非常无语的。 在此类用例中有没有办法获得类似的错误响应?谢谢。

我将从为 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
    }
}