Access request body in check function of express-validator v4

Martin Reiche picture Martin Reiche · Sep 2, 2017 · Viewed 11.6k times · Source

I just started using express.js with express-validator to validate some input data and I have problems accessing the request body in the new check API that was introduced in version 4.0.0.

In older versions, you simply added express-validator as middleware in your app.js somewhere after body-parser:

// ./app.js
const bodyParser = require("body-parser");
const expressValidator = require("express-validator");

const index = require("./routes/index");

const app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(expressValidator());

Then in my index route, I could check the fields in the final callback function of the post method.

// ./routes/index.js
const express = require("express");
const router = express.Router();

router.post("/submit", (req, res, next) => {
    // check email
    req.check('email','Invalid email address').isEmail()
    // check if password is equal to password confirmation
    req.check('password', 'Invalid password')
    /* Access request body to compare password 
    field with password confirmation field */
    .equals(req.body.confirmPassword)

    // get errors
    const errors = req.validationErrors();

    // do stuff
});

Like in this example, I could easily check whether the values of my password field and the password confirmation field of my form are equal. However, since version 4, they have a new API which requires you to load the express-validator directly in your router file and pass the check functions as array of functions before the final callback in the post method, like this:

// ./routes/index.js
const express = require("express");
const router = express.Router();
const { check, validationResult } = require("express-validator/check");

router.post(
    "/submit",
    [
        // Check validity
        check("email", "Invalid email").isEmail(),
        // Does not work since req is not defined
        check("password", "invalid password").isLength({ min: 4 })
        .equals(req.body.confirmPassword) // throws an error
    ],
    (req, res, next) => {
    // return validation results
    const errors = validationResult(req);

    // do stuff
});

This doesn't work since req is not defined. So my quetsion is: how can I access the request object in a check() chain to compare two different fields with the new express-validator API? Thanks very much in advance!

Answer

Martin Reiche picture Martin Reiche · Sep 2, 2017

After fiddling around for a while, I found a way to achieve this by using custom validators. The validator function passed to the custom method accepts an object containing the request body:

router.post(
    "/submit",
    [
    // Check validity
    check("email", "Invalid email").isEmail(),
    check("password", "invalid password")
        .isLength({ min: 4 })
        .custom((value,{req, loc, path}) => {
            if (value !== req.body.confirmPassword) {
                // trow error if passwords do not match
                throw new Error("Passwords don't match");
            } else {
                return value;
            }
        })
    ],
    (req, res, next) => {
        // return validation results
        const errors = validationResult(req);

        // do stuff
    });