Using Express validator πŸ€”

January 26, 2021

Validating input in Express using express-validator

understand how to use express-validator module to make the input validation from the server side. We will build a basic Node/Express app with the help of a couple of npm packages such as express-session, express-validator, cookie-parser, etc.

πŸ‘‰ ⚠️ Express validator is one of the many npm packages for validating a request in an express application.

// ...rest of the initial code omitted for simplicity.
const { check, validationResult } = require('express-validator')

app.post(
  '/user',
  [
    // username must be an email
    check('username').isEmail(),
    // password must be at least 5 chars long
    check('password').isLength({ min: 5 }),
  ],
  (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(422).json({ errors: errors.array() })
    }

    User.create({
      username: req.body.username,
      password: req.body.password,
    }).then(user => res.json(user))
  }
)

That pattern may be okay for a very simple use case but when usage scales, it'd be difficult for the codebase to be maintained and also it makes the route definition not readable.

In this article, I'll be showing how the validation above can be made more readable and easier to maintain.

Step 1

Create a file named validator.js Inside the validator.js, we are going to add two functions, one of the functions will hold the validation rules, while the second will contain the function the does the actual validation.

Copy the snippet below πŸ‘‡ into the validator.js

const { body, validationResult } = require('express-validator')
const userValidationRules = () => {
  return [
    // username must be an email
    body('username').isEmail(),
    // password must be at least 5 chars long
    body('password').isLength({ min: 5 }),
  ]
}

const validate = (req, res, next) => {
  const errors = validationResult(req)
  if (errors.isEmpty()) {
    return next()
  }
  const extractedErrors = []
  errors.array().map(err => extractedErrors.push({ [err.param]: err.msg }))

  return res.status(422).json({
    errors: extractedErrors,
  })
}

module.exports = {
  userValidationRules,
  validate,
}

Step 2

Now re-writing the initial snippet above, we'd have:

const { userValidationRules, validate } = require('./validator.js')
app.post('/user', userValidationRules(), validate, (req, res) => {
  User.create({
    username: req.body.username,
    password: req.body.password,
  }).then(user => res.json(user))
})

Now if you try to register a user without meeting the specification for the user data, the validation error response would look like shown below:

{
    "errors": [
        {
            "username": "username must be an email"
        },
        {
            "password": "password must be at least 5 chars long"
        },
    ]
}

With this method in place, you can define the validation rules for each route or module in a separate file as you may deem fit and then chain it with the validate middleware. That way the code looks much cleaner, easier to read and easier to maintain.

Express Validator Docs

Going further and hands on more practice πŸ‘‡

Why Server-side Validation ❓ πŸ€”

Well, security is the most significant expect when it comes to safety and security; a server must not have total faith on the client-side. The client-side validation can be deciphered, or data can be manipulated by just turning off the JavaScript in the browser. Validation has a significant role in web or mobile application security. No matter whether you build your app using the Express framework or any other Node.js framework. In this tutorial, we will look at how to validate form data in an Express/Node.js app using a popular open-source npm package called express-validator.

Why express-validator is useful?

As per their official documentation: express-validator is a set of express.js middlewares that wraps validator.js validator and sanitizer functions.

πŸ‘‰ Check API

πŸ‘‰ Filter API

πŸ‘‰ Schema Validation

πŸ‘‰ Validation chain API

πŸ‘‰ Validation Result API

πŸ‘‰ Custom Error Messages

πŸ‘‰ Sanitization chain API

πŸ‘‰ Validation MiddleWares

Input Validation with Express Validator Example

We will create an Express API to make the POST request to the server. If the request gets failed, then we will display the form validation errors for name, email, password and confirm password input fields.

We will install Bootstrap 4 to build the basic form and to display the HTML partials we will use up express-hbs module in our Express/Node app.

Set Up Express/Node Form Validation Project

Create express input validation project folder for by running the below command.

mkdir express-node-form-validation

Get inside the project directory.

cd express-node-form-validation

Run command to create package.json:

npm init

Next, install nodemon module with --save-dev attribute for development purpose. This module takes care the server restarting process.

npm install nodemon --save-dev

Install Express Validator Package

Next, install following module from npm to build express and node app.

npm install body-parser cookie-parser cors express-session --save

In order to implement input validation we need to install express and express-validator modules.

npm install express express-validator --save

Configure Node/Express Server

Create app.js file, here in this file we will keep node server settings. Then, go to package.json file and add start: β€œnodemon app.js” property inside the scripts object and also define main: "app.js" property.

Here is the final package.json file.

// package.json

{
  "name": "express-node-server-side-form-validation",
  "version": "1.0.0",
  "description": "Express and Node.js server-side form validation tutorial with examples",
  "main": "app.js",
  "scripts": {
    "start": "nodemon app.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Irie",
  "license": "ISC",
  "dependencies": {
    "body-parser": "^1.19.0",
    "cookie-parser": "^1.4.4",
    "cors": "^2.8.5",
    "express": "^4.17.1",
    "express-hbs": "^2.1.2",
    "express-session": "^1.17.0",
    "express-validator": "^6.2.0"
  },
  "devDependencies": {
    "nodemon": "^1.19.4"
  }
}

Next, go to app.js file and include the following code in it.

const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const cookieParser = require('cookie-parser');
const session = require('express-session');

// Express settings
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
    extended: false
}));
app.use(cors());


app.use(cookieParser());
app.use(session({
    secret: 'positronx',
    saveUninitialized: false,
    resave: false
}));


// Define PORT
const port = process.env.PORT || 3000;
const server = app.listen(port, () => {
    console.log('Connected to port ' + port)
})

Set Up Express Handlebars View Engine

Now, we need to install express-hbs module, It’s a handlbars templating view engine. Run below command to install the module.

npm install express-hbs --save

Next step, create views folder inside the express input validation project folder. And, also create partials folder within the views folder, following will be the folder architecture views > partials.

Then, create public folder inside the express validation folder. Also, create css and js folder inside the public folder.

Next, Download Bootstrap and take bootstrap.min.css and bootstrap.min.js files and put inside their respective folders inside the public folder.

πŸ‘‰ Create user.hbs file using Bootstrap inside views/partials/ folder, add the following code.

<!-- user.hbs -->

<html lang="en">

<head>
    <title>Express Node Form Validation</title>
    <link href="../../public/css/bootstrap.min.css" rel="stylesheet" type="text/css">
    <link href="../../public/css/styles.css" rel="stylesheet" type="text/css">
</head>

<body>
    <nav class="navbar navbar-dark bg-primary">
        <a class="navbar-brand" href="#">Express Form Data Validation</a>
    </nav>

    <div class="container">
        <div class="col-md-12">
            <form method="post" action="">
                <div class="form-group">
                    <label>Name</label>
                    <input type="text" class="form-control" name="name" />
                </div>
                <div class="form-group">
                    <label>Email</label>
                    <input type="text" class="form-control" name="email" />
                </div>
                <div class="form-group">
                    <label>Password</label>
                    <input type="password" class="form-control" name="password" />
                </div>
                <div class="form-group">
                    <label>Confirm Password</label>
                    <input type="password" class="form-control" name="confirm_password" />
                </div>
                <div class="form-group">
                    <button type="submit" class="btn btn-danger btn-block">Create</button>
                </div>
            </form>
        </div>
    </div>
</body>

</html>

Next, add express handlebars view engine settings in app.js file.

// app.js

const hbs = require('express-hbs');


// Serve static resources
app.use('/public', express.static('public'));

// Render View
app.engine('hbs', hbs.express4({
    partialsDir: __dirname + '/views/partials'
}));
app.set('view engine', 'hbs');
app.set('views', __dirname + '/views/partials');

Run the following command bellow and check the user form in the browser in your localhost.

npm start

Implement Input Validation in Express Routes

Now, create express routers to make the POST and GET requests using Express.js. Create πŸ“routes folder and create user.routes.js file inside of it and paste the given below code.

// routes/user.routes.js

const express = require("express");
const session = require('express-session');
const router = express.Router();

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


router.post('/create-user',
    [
        check('name')
            .not()
            .isEmpty()
            .withMessage('Name is required'),
        check('email', 'Email is required')
            .isEmail(),
        check('password', 'Password is required')
            .isLength({ min: 1 })
            .custom((val, { req, loc, path }) => {
                if (val !== req.body.confirm_password) {
                    throw new Error("Passwords don't match");
                } else {
                    return value;
                }
            }),
    ], (req, res) => {
        var errors = validationResult(req).array();
        if (errors) {
            req.session.errors = errors;
            req.session.success = false;
            res.redirect('/user');
        } else {
            req.session.success = true;
            res.redirect('/user');
        }
    });

router.get('/', function (req, res) {
    res.render('user', {
        success: req.session.success,
        errors: req.session.errors
    });
    req.session.errors = null;
});


module.exports = router;

πŸ‘‰ Import check, validationResult class from the express-validator module in the user.routes.js file.

πŸ‘‰ Add input validation with HTTP POST request declare the errors array as a second argument in the router.post() method.

We declared the express validators check() method and passed the input validation name in it, and used the .not(), .isEmpty() methods in it. To display the error message the .withMessage() method was used.

The .isEmail() does the email validation in the Express API.

To make the password required and confirm password validation, we declare the custom method.

πŸ‘‰ Next, go to app.js and add the express user router.

// app.js


// User router
const user = require('./routes/user.routes');


// Initiate API
app.use('/user', user)

Show Server-Side Validation Errors in Node App

To show the validation errors in the handlebar view template. Go, to views/partials/user.hbs file and add the following code in it.

<!-- user.hbs -->

<html lang="en">

<head>
    <title>Express Node Form Validation</title>
    <link href="../../public/css/bootstrap.min.css" rel="stylesheet" type="text/css">
    <link href="../../public/css/styles.css" rel="stylesheet" type="text/css">
</head>

<body>
    <nav class="navbar navbar-dark bg-primary">
        <a class="navbar-brand" href="#">Express Form Data Validation</a>
    </nav>

    <div class="container">
        <div class="col-md-12">
            {{# if errors }}
              {{# each errors }}
                <p class="alert alert-danger">{{ this.msg }}</p>
              {{/each}}
            {{/if}}

            <form method="post" action="/user/create-user">
                <div class="form-group">
                    <label>Name</label>
                    <input type="text" class="form-control" name="name" />
                </div>
                <div class="form-group">
                    <label>Email</label>
                    <input type="text" class="form-control" name="email" />
                </div>
                <div class="form-group">
                    <label>Password</label>
                    <input type="password" class="form-control" name="password" />
                </div>
                <div class="form-group">
                    <label>Confirm Password</label>
                    <input type="password" class="form-control" name="confirm_password" />
                </div>
                <div class="form-group">
                    <button type="submit" class="btn btn-danger btn-block">Create</button>
                </div>
            </form>
        </div>
    </div>
</body>

</html>

πŸ‘‰ Code on GitHub LearningLab - Express-Node-Server-form-Validation

Happy Coding! πŸ’» πŸ€“ 🌴 πŸ’

Up next