Within last week’s tutorial you’ve learned how to access the request payload in hapi. Because you should never, ever trust provided data submitted by users, a common process is to validate the request payload against a given rule set. hapi streamlines this procedure and integrates a validation process for object schemas with the help of joi.
This guide shows you how to use joi and configure payload validation for incoming requests on a given route.
Before diving into the details, have a look at the series outline and find posts that match your interests and needs.
hapi Series Overview
- What You’ll Build
- Prepare Your Project: Stack & Structure
- Environment Variables and Storing Secrets
- Set Up MongoDB and Connect With Mongoose
- Sending Emails in Node.js
- Load the User’s Profile Picture From Gravatar Using Virtuals in Mongoose
- Implement a User Profile Editing Screen
- Generate a Username in Mongoose Middleware
- Displaying Seasons and Episodes for TV Shows with Mongoose Relationship Population
- Implementing Pagination for Movies
- Implement a Watchlist
- Create a Full Text Search with MongoDB
- Create a REST API with JSON Endpoints
- Update Mongoose Models for JSON Responses
- API Pagination for TV Shows
- Customize API Endpoints with Query Parameters
- Always Throw and Handle API Validation Errors
- Advanced API Validation With Custom Errors
- Create an API Documentation with Swagger
- Customize Your Swagger API Documentation URL
- Describe Endpoint Details in Your Swagger API Documentation
- 10 Tips on API Testing With Postman
- JWT Authentication in Swagger API Documentation
- API Versioning with Request Headers
- API Login With Username and Password to Generate a JWT
- JWT Authentication and Private API Endpoints
- Refresh Tokens With JWT Authentication
- Create a JWT Utility
- JWT Refresh Token for Multiple Devices
- Check Refresh Token in Authentication Strategy
- Rate Limit Your Refresh Token API Endpoint
- How to Revoke a JWT
- Invalidate JWTs With Blacklists
- JWT Logout (Part 1/2)
- JWT “Immediate” Logout (Part 2/2)
- A Better Place to Invalidate Tokens
- How to Switch the JWT Signing Algorithm
- Roll Your Own Refresh Token Authentication Scheme
- JWT Claims 101
- Use JWT With Asymmetric Signatures (RS256 & Co.)
- Encrypt the JWT Payload (The Simple Way)
- Increase JWT Security Beyond the Signature
- Unsigned JSON Web Tokens (Unsecured JWS)
- JWK and JWKS Overview
- Provide a JWKS API Endpoint
- Create a JWK from a Shared Secret
- JWT Verification via JWKS API Endpoint
- What is JOSE in JWT
- Encrypt a JWT (the JWE Way)
- Authenticate Encrypted JWTs (JWE)
- Encrypted and Signed JWT (Nested JWT)
- Bringing Back JWT Decoding and Authentication
- Bringing Back JWT Claims in the JWT Payload
- Basic Authentication With Username and Password
- Authentication and Remember Me Using Cookies
- How to Set a Default Authentication Strategy
- Define Multiple Authentication Strategies for a Route
- Restrict User Access With Scopes
- Show „Insufficient Scope“ View for Routes With Restricted Access
- Access Restriction With Dynamic and Advanced Scopes
- hapi - How to Fix „unknown authentication strategy“
- Authenticate with GitHub And Remember the Login
- Authenticate with GitLab And Remember the User
- How to Combine Bell With Another Authentication Strategy
- Custom OAuth Bell Strategy to Connect With any Server
- Redirect to Previous Page After Login
- How to Implement a Complete Sign Up Flow With Email and Password
- How to Implement a Complete Login Flow
- Implement a Password-Reset Flow
- Views in hapi 9 (and above)
- How to Render and Reply Views
- How to Reply and Render Pug Views (Using Pug 2.0)
- How to Create a Dynamic Handlebars Layout Template
- Create and Use Handlebars Partial Views
- Create and Use Custom Handlebars Helpers
- Specify a Different Handlebars Layout for a Specific View
- How to Create Jade-Like Layout Blocks in Handlebars
- Use Vue.js Mustache Tags in Handlebars Templates
- How to Use Multiple Handlebars Layouts
- How to Access and Handle Request Payload
- Access Request Headers
- How to Manage Cookies and HTTP States Across Requests
- Detect and Get the Client IP Address
- How to Upload Files
- Quick Access to Logged In User in Route Handlers
- How to Fix “handler method did not return a value, a promise, or throw an error”
- How to Fix “X must return an error, a takeover response, or a continue signal”
- Query Parameter Validation With Joi
- Path Parameter Validation With Joi
- Request Payload Validation With Joi
- Validate Query and Path Parameters, Payload and Headers All at Once on Your Routes
- Validate Request Headers With Joi
- Reply Custom View for Failed Validations
- Handle Failed Validations and Show Errors Details at Inputs
- How to Fix AssertionError, Cannot validate HEAD or GET requests
Prepare Your Project and Install Joi
You’ll use the joi
module from within hapi’s plugin ecosystem to validate selected fields within the request payload. Before defining the validation itself, you need to add joi
as a dependency to your project:
npm i -S joi
Installation process finished successfully? Your project is prepared to make use of joi
for input validation.
Use Joi for Payload Validation
Incoming requests pass a pre-defined list of actions like route lookup that matches the request’s path, parse cookies, authenticate the request, parse payload and many more. Once the request payload is parsed and available, the validation procedure gets kicked off. If you didn’t define any validation, hapi skips this step and proceeds with the route handler.
In case you’ve payload validation in place, hapi applies the defined constraints. Depending on whether the given payload data passes the validation process successfully, the request will be proceeded by calling the route handler. If validation fails, hapi will reply with a detailed boom error object including the reason why validation failed.
Let’s get practical and have a look at code that illustrates the application of payload validation for a given hapi route. The route’s handler
is located aside the validate
configuration within the config
object of your route:
var Joi = require('joi')
server.route({
method: 'POST',
path: '/',
config: {
handler: …,
validate: {
payload: {
email: Joi.string().email().required(),
password: Joi.string().min(6).max(200).required()
}
}
}
})
As you can see, the validate
object requires you to further specify the validation type, like payload
, query
parameter and params
which describes the path parameters. Within your individual payload
object, define the properties that will be checked for incoming requests.
In the example above, you can see that the email
and password
fields within the request payload will be validated against the given joi
rules. email
needs to be a valid email string and is a required field. password
is a string with a minimum length of 6, maximum length of 200 characters and also a required property. Of course, you can define your validation rules of choice. Within Joi’s API documentation, you’ll find all applicable methods.
In case the validation doesn’t pass successfully, you’ll receive the aforementioned boom
error object. The following code block shows the detailed raw response payload that will be sent to the requester.
Raw Response Payload
{
"statusCode": 400,
"error": "Bad Request",
"message": "child \"password\" fails because [\"password\" length must be at least 6 characters long]",
"validation": {
"source": "payload",
"keys": [
"password"
]
}
}
Actually, you’ll receive a proper 400 Bad Request
HTTP response and the content from the code snippet above is contained within the response body.
The message
property indicates the error details and what to adjust within future requests to avoid the issue. Within the validation
field, you can find the keys that caused the error. Also, the error object contains the statusCode
and HTTP error
as individual fields.
Outlook
We hope you enjoyed this guide on payload validation and take away the insights on how to improve your code by validating fields as early as possible. Validating incoming user data as early will keep your code base clean and small. You don’t need to perform the validation steps yourself within the route handler.
Benefit from hapi’s functionality and put in some brainpower to get going with joi
and what rules are applicable for the request payload, query and path parameters.
The request payload isn’t the only option to pass data from clients to server. Validate query parameters as well.
We appreciate feedback and love to help you if there’s a question on your mind. Let us know in the comments or on twitter @futurestud_io.
Make it rock & enjoy coding!
Additional Resources
- Joi validation library on GitHub
- Joi API describing available validation methods
- HTTP-friendly error handling: boom
- Tutorial on handling request payload in hapi