Search code examples
javascriptnode.jsexpressvalidationexpress-validator

How to make a function validator for express-validator and use it as Middleware?


I have this validator in my register route:

router.post(
  "/register",
  // username must be an email
  body("username")
    .isLength({ min: 4 })
    .withMessage("username must be at least 4 chars long")
    .isLength({ max: 12 })
    .withMessage(" username must be less than 12 chars long")
    .exists()
    .withMessage("username is required")
    .trim()
    .matches(/^[A-Za-z0-9\_]+$/)
    .withMessage("username must be alphanumeric only")
    .escape(),
  body("email")
    .isEmail()
    .normalizeEmail()
    .withMessage("Invalid Email")
    .exists(),
  body("password")
    .isLength({ min: 5 })
    .withMessage("password must be at least 5 chars long")
    .isLength({ max: 30 })
    .withMessage("password must be at max 30 chars long")
    .matches(/\d/)
    .withMessage("password must contain a number")
    .exists(),
  (req, res) => {
    // Finds the validation errors in this request and wraps them in an object with handy functions
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array() });
    }
    const username = Utils.Clean_input(req.body.username);
    const email = Utils.Clean_input(req.body.email);
    const password = Utils.Clean_input(req.body.password);
    const salthash = Utils.genPassword(password);
    const salt = salthash.salt;
    const hash = salthash.hash;
    const newuser = new User({
      username: username,
      email: email,
      hash: hash,
      salt: salt,
    });
    try {
      newuser.save((err, data) => {
        if (data) {
          res.status(201).json({
            status: 201,
            sucess: true,
            message: "Register Success, verify your email and login",
          });
        } else {
          res.status(400).json({ err });
        }
      });
    } catch (error) {
      res.status(500).json({ errors: "Server is down try again later" });
    }
  }
);

Can I put those validations method in a custom function in another .js file and import them? If yes how?

example: router.post("/register",validation_fucntion,(res,req){..}), the validation_function handle the validation from another .js file which is imported to the project


Solution

  • express middleware can also be declared in an array for reusability. So you can create the validation function that returns an array with the validators.

    E.g.

    app.ts:

    import express from 'express';
    import { body, validationResult } from 'express-validator';
    
    function UserRegisterValidation() {
      return [
        body('username')
          .isLength({ min: 4 })
          .withMessage('username must be at least 4 chars long')
          .isLength({ max: 12 })
          .withMessage(' username must be less than 12 chars long')
          .exists()
          .withMessage('username is required')
          .trim()
          .matches(/^[A-Za-z0-9\_]+$/)
          .withMessage('username must be alphanumeric only')
          .escape(),
        body('email').isEmail().normalizeEmail().withMessage('Invalid Email').exists(),
        body('password')
          .isLength({ min: 5 })
          .withMessage('password must be at least 5 chars long')
          .isLength({ max: 30 })
          .withMessage('password must be at max 30 chars long')
          .matches(/\d/)
          .withMessage('password must contain a number')
          .exists(),
      ];
    }
    
    const app = express();
    const port = 3000;
    
    app.use(express.json());
    app.post('/register', UserRegisterValidation(), (req, res) => {
      const errors = validationResult(req);
      if (!errors.isEmpty()) {
        return res.status(400).json({ errors: errors.array() });
      }
      res.sendStatus(200);
    });
    
    app.listen(port, () => console.log('HTTP server started at port 3000'));
    

    Test:

    ⚡  curl -i -X POST -H "Content-Type: application/json"  -d '{"username": "teresa teng"}' http://localhost:3000/register            
    HTTP/1.1 400 Bad Request
    X-Powered-By: Express
    Content-Type: application/json; charset=utf-8
    Content-Length: 295
    ETag: W/"127-wBnvezB+j1d3j/nM62Y93ii4FtM"
    Date: Thu, 09 Dec 2021 02:49:12 GMT
    Connection: keep-alive
    Keep-Alive: timeout=5
    
    {"errors":[{"msg":"Invalid Email","param":"email","location":"body"},{"msg":"password must be at least 5 chars long","param":"password","location":"body"},{"msg":"password must contain a number","param":"password","location":"body"},{"msg":"Invalid value","param":"password","location":"body"}]}% 
    
     ⚡  curl -i -X POST -H "Content-Type: application/json"  -d '{"username": "teresa teng", "password": "password123", "email": "test@gmail.com"}' http://localhost:3000/register
    HTTP/1.1 200 OK
    X-Powered-By: Express
    Content-Type: text/plain; charset=utf-8
    Content-Length: 2
    ETag: W/"2-nOO9QiTIwXgNtWtBJezz8kv3SLc"
    Date: Thu, 09 Dec 2021 02:45:04 GMT
    Connection: keep-alive
    Keep-Alive: timeout=5
    
    OK%