【问题标题】:express-validator returns validation errors twiceexpress-validator 两次返回验证错误
【发布时间】:2020-01-23 22:13:03
【问题描述】:

我想使用 Express-Validator 验证请求对象。假设我有两条路线,一条 GET /users/:id (fetchUserById) 和 POST /users (createUser) 路线

this.router = express.Router();
this.router.route('/').post(this.userRequestValidator.createUser, this.userController.createUser);
this.router.route('/:id').get(this.userRequestValidator.fetchUserById, this.userController.fetchUserById);

如您所见,我在调用控制器逻辑之前调用了验证中间件。首先,我创建了一个基本验证器来处理验证错误并在失败时返回 HTTP 400。

export abstract class RequestValidator {
    protected validate = async (request: Request, response: Response, next: NextFunction): Promise<void> => {
        const errors: Result<ValidationError> = validationResult(request);

        if (!errors.isEmpty()) {
            return res.status(422).json({ errors: errors.array() });
        } else {
            next();
        }
    };
}

我的验证器函数 userRequestValidator.createUseruserRequestValidator.fetchUserById 只需要扩展 RequestValidator 并实现验证

export class UserRequestValidator extends RequestValidator {
    public createUser = [
        body('username')
            .isString()
            .exists(),
        body('password')
            .isString()
            .exists(),
        this.validate,
    ];

    public fetchUserById = [
        param('id')
            .isString()
            .isUUID()
            .exists(),
        this.validate,
    ];
}

当我致电 GET localhost:3000/users/abc 时,我会收到此回复

{
    "errors": [
        {
            "value": "abc",
            "msg": "Invalid value",
            "param": "id",
            "location": "params"
        }
    ]
}

这是我期待的回应。但是当我用一个空的身体打电话给POST localhost:3000/users 时,我得到了这个回复

{
    "errors": [
        {
            "msg": "Invalid value",
            "param": "username",
            "location": "body"
        },
        {
            "msg": "Invalid value",
            "param": "username",
            "location": "body"
        },
        {
            "msg": "Invalid value",
            "param": "password",
            "location": "body"
        },
        {
            "msg": "Invalid value",
            "param": "password",
            "location": "body"
        }
    ]
}

有人知道我可以如何解决此问题或我的设置有什么问题吗?

【问题讨论】:

  • 您使用的是哪个版本的 express-validator?

标签: javascript node.js typescript express express-validator


【解决方案1】:

我不知道为什么当req.body 是一个空对象-{} 时,验证器会遍历验证链的所有节点。您可以再次检查,为每个条件添加每个消息,如下所示:

class UserRequestValidator extends RequestValidator {
  public createUser = [
    body('username')
      .isString().withMessage('username must be a string') // you can see both error messages in the response
      .exists().withMessage('username must be exist'),
    body('password') // the same for this field
      .isString()
      .exists(),
    this.validate,
  ];

  public fetchUserById = [
    param('id') // because id is exist in `req.params`, then only one test has been executed.
      .isString().withMessage('id must be a string')
      .isUUID()
      .exists(),
    this.validate,
  ];
}

我在 https://github.com/express-validator/express-validator/issues/638 找到了适合您情况的解决方案,使用 .bail() 函数在第一个错误中停止链。

那么你的验证器类将是这样的:

class UserRequestValidator extends RequestValidator {
  public createUser = [
    body('username')
       // always check exists() first
      .exists().withMessage('username must be exist').bail()
      .isString().withMessage('username must be a string').bail(),
    body('password')
      .exists().bail()
      .isString().bail(),
    this.validate,
  ];

  public fetchUserById = [
    param('id')
      .isString()
      .isUUID()
      .exists(),
    this.validate,
  ];
}

【讨论】:

  • 对不起,我可以在 11 小时内奖励赏金
【解决方案2】:

您也可以在检索错误数组时将onlyFirstError 设置为true。 来自documentation

如果选项 onlyFirstError 设置为 true,那么只有第一个错误 将包含每个字段

示例用法:

function validateRequestParams (req, res, next) {
    const errors = validationResult(req)

    if (errors.isEmpty()) {
        return next()
    } else {
        return res.status(400).json({
            bodyValidationErrors: errors.array({ onlyFirstError: true })
        })
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-23
    • 2022-08-05
    • 1970-01-01
    • 1970-01-01
    • 2013-07-11
    • 2012-09-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多