express-validator:是否可以链接不同的用户验证规则?

express-validator: is it possible to chain different user validation rules?

我有以下几乎相似的规则除了一个路由参数是可选的而另一个是强制性的。 需要将它们组合起来,以便我可以将单个代码互换地用于强制条件和其他可选条件

有没有办法将它们组合起来,这样我就没有多余的代码了?

const pathParamValidation = check('convertedUrlId')
  .isLength({ min: 5, max: 6 })
  .withMessage({
    error: 'Invalid length',
    detail: {
      convertedUrlId:
        'Invalid Length! Character length >=5 and <7 characters are allowed',
    },
  })
  .matches(/^[~A-Za-z0-9/./_/-]*$/)
  .withMessage({
    error: 'Invalid characters',
    detail: {
      convertedUrlId:
        'Invalid characters! Only [A-Z],[a-z],[0-9], _ , - , . , ~ are allowed',
    },
  });

#可选

const optionalConvertedUrlIdValidation = check('convertedUrlId')
  .optional()
  .matches(/^[~A-Za-z0-9/./_/-]*$/)
  .withMessage({
    error: 'Invalid characters',
    detail: {
      convertedUrlId:
        'Invalid characters! Only [A-Z],[a-z],[0-9], _ , - , . , ~ are allowed',
    },
  })
  .isLength({ min: 5, max: 6 })
  .withMessage({
    error: 'Invalid length',
    detail: {
      convertedUrlId:
        'Invalid Length! Character length >=5 and <7 characters are allowed',
    },
  });

我试过用这种方式组合,但是没有成功

const checkConvertedUrlSchema = check('convertedUrlId')
  .matches(/^[~A-Za-z0-9/./_/-]*$/)
  .withMessage({
    error: 'Invalid characters',
    detail: {
      convertedUrlId:
        'Invalid characters! Only [A-Z],[a-z],[0-9], _ , - , . , ~ are allowed',
    },
  });

const checkConvertedUrlLength = check('convertedUrlId')
  .isLength({ min: 5, max: 6 })
  .withMessage({
    error: 'Invalid length',
    detail: {
      convertedUrlId:
        'Invalid Length! Character length >=5 and <7 characters are allowed',
    },
  });

const convertedUrlIdValidation =
  check('convertedUrlId').checkConvertedUrlLength.checkConvertedUrlSchema;
const optionalConvertedUrlIdValidation =
  check('convertedUrlId').optional().checkConvertedUrlSchema
    .checkConvertedUrlLength;

您可以创建验证器工厂来创建通用验证规则。

import { body, validationResult } from 'express-validator';
import express from 'express';
const app = express();

const convertedUrlIdValidationFactory = () =>
  body('convertedUrlId')
    .isLength({ min: 5, max: 6 })
    .withMessage({
      error: 'Invalid length',
      detail: {
        convertedUrlId: 'Invalid Length! Character length >=5 and <7 characters are allowed',
      },
    })
    .matches(/^[~A-Za-z0-9/./_/-]*$/)
    .withMessage({
      error: 'Invalid characters',
      detail: {
        convertedUrlId: 'Invalid characters! Only [A-Z],[a-z],[0-9], _ , - , . , ~ are allowed',
      },
    });

app.use(express.json());
app.post('/optional', convertedUrlIdValidationFactory().optional(), (req, res) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(400).json({ errors: errors.array() });
  }
  console.log(req.body);
  res.sendStatus(200);
});

app.post('/required', convertedUrlIdValidationFactory(), (req, res) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(400).json({ errors: errors.array() });
  }
  console.log(req.body);
  res.sendStatus(200);
});

app.listen(3000, () => console.log('server started at port 3000'));

测试用例1:没有convertedUrlId数据。

 ⚡  curl -X POST http://localhost:3000/required
{"errors":[{"msg":{"error":"Invalid length","detail":{"convertedUrlId":"Invalid Length! Character length >=5 and <7 characters are allowed"}},"param":"convertedUrlId","location":"body"}]}%

⚡  curl -X POST http://localhost:3000/optional
OK%  

测试用例2:有一个convertedUrlId数据。

⚡  curl -X POST -H "Content-Type: application/json" --data '{"convertedUrlId": "12345"}' http://localhost:3000/required
OK% 

⚡  curl -X POST -H "Content-Type: application/json" --data '{"convertedUrlId": "12345"}' http://localhost:3000/optional
OK%

这对我有用

const checkConvertedUrlSchema = (chain) =>
  chain.matches(/^[~A-Za-z0-9/./_/-]*$/).withMessage({
    error: 'Invalid characters',
    detail: {
      convertedUrlId:
        'Invalid characters! Only [A-Z],[a-z],[0-9], _ , - , . , ~ are allowed',
    },
  });

const checkConvertedUrlLength = (chain) =>
  chain.isLength({ min: 5, max: 6 }).withMessage({
    error: 'Invalid length',
    detail: {
      convertedUrlId:
        'Invalid Length! Character length >=5 and <7 characters are allowed',
    },
  });

const checkConvertedUrlIdBodyValidation = (chain) =>
  chain
    .not()
    .isEmpty()
    .withMessage({
      error: 'Invalid Request Body',
      detail: {
        convertedUrlId:
          'Request Syntax Error! convertedUrlId parameter is required',
      },
    });

const convertedUrlIdBodyValidation = checkConvertedUrlLength(
  checkConvertedUrlSchema(
    checkConvertedUrlIdBodyValidation(check('convertedUrlId'))
  )
);

const convertedUrlIdValidation = checkConvertedUrlLength(
  checkConvertedUrlSchema(check('convertedUrlId'))
);
const optionalConvertedUrlIdValidation = convertedUrlIdValidation.optional();