Welcome again! If you reached this post from nowhere and don’t understand what all this is about, you can check out the previous posts:
- 1. Intro and Initial Setup
- 2. Setting up the Web Server
- 3. The Database: Setup
- 4. The Database: Connect and Config
- 5. The Endpoints
- 6. Security with JWT
You can find the code for this tutorial in GitHub.
If you followed the steps from the previous posts your project directory structure should look like this:
If it doesn’t, please go back and check if you missed something from the previous posts.
Request Payload Validation
We have now a set of endpoints to manage users and tasks, and secured with JWT to avoid unknown clients to access our API. Now we’ll have a look at how can we add some validation to the request payload sent by clients. Since we want to keep our database consistent, it’s good to check what the user is sending us. You can do validations in different levels. In the top level, you can validate data types and format of parameters, and in the next level you can validate that a resource ID sent by the user exists in the database.
During this post we’ll focus on the first level, which is validating the data types and the format of the data sent by the user. The second level explained before can be easily done with a database query at the beginning of your endpoint controller.
We’ll be using a few handy modules for the validation purpose:
express-validationprovides a middleware function that can validate the request payload data given a set of rules provided by us.
joiit’s the module we’ll use to define those rules
The Validation Rules
Let’s start by creating our validation rules. I’ll explain how to create this rules for the tasks endpoints, you can replicate easily the same approach for the rest of your API routes.
Go to the
server/routes directory and create there a new directory called
validation. Here we’ll store all the
validation rules for our routes. The rule will be same name for both route and validation file. In our case we’re
writing validations for the
server/routes/tasks.js route file, so we’ll create a
file. Once created, put the following contents on it:
Here we use some of the utilities provided by
joi to validate fields. Joi has a very simple but complete API to do
validations of request data. Let’s take the
body.user: we define that the user parameter in the request body must be a
string, must match the provided regular expression (which is just a regex to match MongoDB ObjectIds) and it’s
body.description: we define that the description parameter in the request body must be a
body.done: we define the done parameter as a
boolean. Note that we don’t place the
requiredvalidation since this field is not required by our API and will have a default value of
falsein case it’s missing.
Simple right? If you have a look at the
getTask definition, we wrote a different set of rules called
bodyrules will validate the data sent with the request payload
paramsrules will validate the data sent as request path parameters
getTask validation will run for all the endpoints that have a
taskId path parameter.
There are three other kind of rules available which we’re not using:
querywill validate the data sent in the request query parameters (things after the first
?in the URL)
headerwill validate the data sent in the request headers.
cookieswill validate data sent on the request cookies.
This validation groups (body, params, query, header, cookies) are defined by the other library we’ll be using (express-validation). If you want a full set of validations provided by Joi you can check the module API page.
The Validation Middleware
Now that we have our set of rules defined, it’s time to use them in our routes. So open the
and let’s add a few lines on it:
The first thing added is the two
import statements, one for
express-validation and other for the validation rules
created in the step before.
Then let’s have a look at the end of the file, where we added an extra middleware for the
Here is where we define the validation of the
taskId path parameter. If the
taskId does not pass the validation, then
the API will answer with
400 Bad Request and stop the middleware execution chain.
There are two other changes done in the route configuration file:
- In the
POST /tasksendpoint, where we add the validation middleware before the endpoint controller function.
- In the
PUT /tasks/taskIdendpoint, where we add the validation before the endpoint controller function as well. In this case, two validation middlewares will be executed. The first one will be the one that validates the
taskIdpath parameter, and the second one will validate the request body data sent to update the corresponding task information.
All set, let’s try the endpoints with some invalid data and see what happens. Grab a console and throw some requests on it:
Good! We got back our expected
400 Bad Request. But we can do a lot better with error messages. Just telling the
client there’s a
validation error is not enough. Imagine when you have complex endpoints where lots of data has to
be sent in the request body. The client would need to check one by one the fields to see which one is incorrect.
Let’s go to the
config/express.js server and tune up a bit the error handling middleware:
So basically we’re delegating the error message details to the express validation module which can provide detailed information about the error. If you try again the same request, you’ll get something like this now:
Much better! Now clients can easily understand what’s wrong with their requests. Now you can add validations to all of your endpoints.
Coming up next…
We’re almost done with our API, the last post will be dedicated to unit testing our endpoints to prevent failures with future changes. So if you’re ready for it, head over to the next post!
If you enjoyed reading, retweet or like this tweet!
How to validate requests on our #express #api using express-validation and @hapijs #Joi libraryhttps://t.co/crEJdS1pr8— Mauricio Payetta (@mpayetta) 3 de agosto de 2016
Building a Node.js REST API 7: Request Validation by Mauricio Payetta is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License .