Экспресс-валидатор дважды возвращает ошибки валидации - PullRequest
4 голосов
/ 23 сентября 2019

Я хочу проверить объект запроса с помощью 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.createUser и userRequestValidator.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"
        }
    ]
}

Кто-нибудь знает, как я могу исправить это поведение или что не так с моей настройкой?

1 Ответ

2 голосов
/ 26 сентября 2019

Я не знаю, почему, когда 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()function.

Тогда ваш класс валидатора будет выглядеть так:

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,
  ];
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...