How to implement validation in a separate file using express-validator

11,943

Solution 1

I have same approach, except one thing that is we shouldn't handle validation error in our controller. So If any error is occurring at Validation Layer, it should throw back from there only. We shouldn't allow our control flow to enter into the Controller Layer. So below are the code example:

useRoute.js

const route = express.Router();

const {
  **validateUser**,
} = require('../middlewares/validators/userValidator');

route.route('/').post(**validateUser**, createUser);
route.route('/:id').put(**validateUser**, updateUser);

module.exports = route;

userValidator.js

const {check, validationResult} = require('express-validator');

exports.validateUser = [
  check('name')
    .trim()
    .escape()
    .not()
    .isEmpty()
    .withMessage('User name can not be empty!')
    .bail()
    .isLength({min: 3})
    .withMessage('Minimum 3 characters required!')
    .bail(),
  check('email')
    .trim()
    .normalizeEmail()
    .not()
    .isEmpty()
    .withMessage('Invalid email address!')
    .bail(),
  (req, res, next) => {
    const errors = validationResult(req);
    if (!errors.isEmpty())
      return res.status(422).json({errors: errors.array()});
    next();
  },
];

controller.js

/**
 * @desc    - create new User
 * @method  - POST
 */
exports.createCategory = async (req, res) => {
  //  do your stuff here. (No need to check any validation error here)
}

Solution 2

Here is the way i use express-validator. I have a file validator.js where i have validation logic for many routes. For example:

validator.js

const { check } = require('express-validator/check');

exports.createUser = [check('email').isEmail()];

exports.anotherRoute = [// check data];

exports.doSomethingElse = [// check data];

Now in your route file you require the validator.js file
const validator = require("./validator"); // or where your file is located
and use the validation logic you want as a middleware. For example:

route.js

//

router.post('/createuser', validator.createUser, usersController.createUser);

Last, inside your controller you have to check for possible errors created during validation, after requiring validationResult.

controller.js

const { validationResult } = require('express-validator/check');


exports.createUser(req, res) {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
        return res.status(422).json({ errors: errors.array() });
    }
    // do stuff here.

}

Also, you don't have to use app.use(expressValidator); in your server.js file

Solution 3

I was running into a few problems with async functions, here is my humble solution hope this helps someone:

Route Definitions

const router = require('express').Router();

const userValidator = require('./Validators/UserValidator');
const userController = require('./Controllers/UserController');

router.post('/users', userValidator.add, userController.add);

Validator

const { check, validationResult } = require('express-validator');

const generateValidators = () => [
    check('first_name')...,
    
    check('last_name')...,
    
    check('email')...,
    
    check('password')...
]

const reporter = (req, res, next) => {
    const errors = validationResult(req);

    if (!errors.isEmpty()) {
        const errorMessages = errors.array().map(error => error.msg);
        
        return res.status(400).json({
            errors: errorMessages
        });
    }
    
    next();
}

module.exports = {
    add: [
        generateValidators(),
        reporter
    ]
};
Share:
11,943
Micah Bala
Author by

Micah Bala

Updated on July 04, 2022

Comments

  • Micah Bala
    Micah Bala almost 2 years

    I am trying to use express-validator to validate the req.body before sending a post request to insert data to postgres.

    I have a route file, controller file and I want to carryout validation in a file called validate.js. Meanwhile, I have installed express-validator and in my server.js I have imported it. Other resources I come across seem to implement the validation in the function that contains the logic for inserting the data.

    //server.js
    ....
    import expressValidator from 'express-validator';
    
    ...
    app.use(bodyParser.urlencoded({ extended: false }));
    app.use(expressValidator);
    
    
    //route.js
    import express from 'express';
    import usersController from './controller';
    
    const router = express.Router();
    
    router.post('/createuser', usersController.createUser);
    
    
    //controller.js
    createUser(req, res){
      // ...
      const { firstName, lastName, email, password } = req.body;
      //code to insert user details to the database
    }
    
    
    //validator.js
    import { check } from 'express-validator/check';
    
    module.exports = [check('email').isEmail()];
    

    I expect to implemet the validation in a file called validator.js to, say, validate the email before inserting to the database

  • Micah Bala
    Micah Bala about 5 years
    Thanks @dimitris I tried the solution you gave, and I don't get anything inserted into the database and I dont get any errors, the request like takes forever.
  • Micah Bala
    Micah Bala about 5 years
    No I did not alter the controller or check for any errors
  • Oscar R
    Oscar R over 4 years
    Works great! Thankss
  • S.alhaider
    S.alhaider almost 4 years
    hello i'm new to node can i ask why you used the brackets instead of callback function
  • Davinder Kumar
    Davinder Kumar about 3 years
    What if I want to pass rules in generateValidators conditionally o basis which action user has passed in req object (in api case) ?
  • Max O.
    Max O. about 2 years
    While the solution works, I would discourage following the advice of handing the error in the validator instead of the controller