In this tutorial I will teach you how to validate user input using an Express middleware module called express-validator.
express-validator is built on top of another open-source library called validator. validator is basically a library of validation functions. Some of it's popular functions include isEmail
and isNumeric
but you can see a full list here. express-validator makes all the functions in validator available in a way that works nicely with Node and Express.
###Installation
Installing express-validator is easy when you use npm. Just input the following command:
npm install express-validator
This will download the latest version of the express-validator npm package.
Once the download has finished, if you look inside of the "node_modules" folder, you'll see that express-validator has a transitive dependency on validator.
###Configuration
I am going to assume that you have an "app.js" file whose contents look something like this:
// dependencies
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
// middleware
app.use(bodyParser.urlencoded({ extended: false }));
(If you do not, you can quickly create a application skeleton using express generator.)
express-validator is simply another middleware module. You hook it up exactly like you would any other middleware, like this:
// dependencies
var express = require('express');
var bodyParser = require('body-parser');
var validator = require('express-validator');
var app = express();
// middleware
app.use(bodyParser.urlencoded({ extended: false }));
app.use(validator());
There is only one thing you need to watch out for and that is, you must “use” express-validator immediately after you “use” the body parser middleware otherwise the middleware might not work.
###Validation
Imagine that you have a handler function like this one:
app.post('/pages/create', function(req, res) {
});
And that the request body looks like this:
{
leader_email: "[email protected]",
leader_mobile_no: "017171",
team_twitter: "http://twitter.com/teamA",
member_count: 10,
page_color: "#FFFFFF",
page_accent_colour: "#FFFFFF"
}
Here we want to validate that
- leader_email is a valid email address*
- leader_mobile_no is a valid UK mobile phone number
- team_twitter is a valid Twitter handle
- member_count is both a number and divisble by 2
- page_color and page_accent_color are valid hex color codes
* Remember. Validation is not the same as verification. Validation merely confirms that the email is in the correct format. Verification confirms that that the user has access to the email. If you need to verify the email, consider sending a verification email.
Validating an email is a common requirement so I will start there. Inside of the handler function that I mentioned earlier, call a function called checkBody
and pass to that function the name of the input element and the desired error message:
req.checkBody("leader_email", "Enter a valid email address.");
Next, chain onto that function call another function call to one or more functions from the validator library. In this case, we will use the isEmail
validation function:
req.checkBody("leader_email", "Enter a valid email address.").isEmail();
The checkBody
function is made available by the express-validation middleware. You can also check the query string using checkQuery
or the params using checkParams
. See the documentation for more information on that.
Hopefully now you can see why express-validator being built on validator is not merely an implementation detail. You almost always end up calling functions from the validator library of validation functions. You can see a full list of validation functions here.
Here is how I would validate the remaining input elements:
req.checkBody("leader_email", "Enter a valid email address.").isEmail();
req.checkBody("leader_mobile_no", "Enter a valid UK phone number.").isMobilePhone("en-GB");
req.checkBody("team_twitter", "Enter a valid Twitter URL").optional().matches("http://twitter.com/*");
req.checkBody("contestant_count", "Contestant count must be a number and one that is divisible by 2").isNumber().isDivisibleBy(2);
req.checkBody("page_color", "Page colour must be a valid hex color").isHexColor();
req.checkBody("page_color_accent", "Page colour accent must be a valid hex color").isHexColor();
Notice how I call a function called optional
before calling the matches
function, which matches an arbitrary regular expression. The optional
function says “this value is optional so do not attempt to validate it unless the user actually entered a value”.
Also notice that in the case of the contestant_count_input we chained two validation functions.
Now that we have defined our validation rules, we need to determine whether the input adheres to them. If not, we need to cease execution and show the user the errors.
To determine whether the input is valid or not, call a function called validationErrors
. If this function returns no errors, the input is valid; otherwise, it is invalid and we must show the returned errors to the user:
var errors = req.validationErrors();
if (errors) {
res.send(errors);
return;
}
// normal processing here
Spitting out raw errors like this is not very nice. That is why it is common to send errors back with a template:
var errors = req.validationErrors();
if (errors) {
res.render('create', { errors: errors });
return;
}
// normal processing here
And then in your template, to show the errors conditionally:
if errors
ul
for error in errors
li!= error.msg
This is an example using the Jade template engine. I know not everyone loves Jade so for good measure, here is another example, this time using the Handlebars template engine:
{{ #if errors }}
<ul>
{{ #each errors }}
<li>{{ this.msg }}</li>
{{ /each }}
</ul>
{{ /if }}
###Custom validation functions
Sometimes your custom validation rules are just too complicated to express using a regular expression and the matches
function. It is for this reason that express-validator enables you to define custom validation functions.
To illustrate custom validation functions, imagine that the user is asked to enter exactly two comma-delimited tags.
- The request body
{ tags: “tag1, tag2” }
would be valid - as where the request bodies
{ tags: “tag1, tag1” }
and{ tags: “tag1” }
would be invalid
Although it might be possible to create a regular expression for this rule, I speculate that doing so would come at too much of a cost to readability. So, let us define a custom validation function.
Inside of the "app.js" file, replace:
app.use(validator());
With:
app.use(validator({
customValidators: {
containsTwoTags: function (value) {
var tags = value.split(',');
// Remove empty tags
tags = tags.filter(function(tag) { return /\S/.test(tag) });
// Remove duplicate tags
tags = tags.filter(function(item, pos, self) { return self.indexOf(item) == pos; });
return tags.length <= 2;
}
}
})
This custom validation function called containsTwoTags
returns true
if the input is valid; otherwise, it returns false
. You can execute any code you want in your custom validation function so long as it returns a boolean.
You can use this custom validation function just like you would any other validation function, like this:
req.checkBody('tags', 'Enter exactly two distinct tags.').containsTwoTags();
Pretty sweet…
###Summary This has been a basic introduction to input validation in Node with express-validator. Whilst I hope I have covered enough for you to hit the ground running in your application, if you encounter any trouble, please consult the documentation or get in touch and I will be happy to help.