In an advanced development state, you want to make use of request headers and because you don’t blindly trust the incoming values, you also apply validation rules. With hapi, you’ve a framework that has validation built into its core and makes it easy to define rules for request headers and this tutorial walks you through the setup of request header validation.
A quick heads up before moving on. This hapi series includes tutorials on various topics. Check out the series overview and make progress with ease.
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
Once the installation finished successfully, your project is prepared to make use of joi
for object validation.
Validate Request Headers Using Joi
Requests sent from clients (e.g. browsers or mobile apps) will always contain multiple request headers, like properties for user-agent
, accept
, accept-encoding
, and many more. Of course, all the request headers have their specific need and are evaluated and used by different tools.
Let’s imagine the following scenario: you want to keep track of all the different applications, tools and libraries that clients use to request your API. That’s why you set a required
rule for the user-agent
header and only requests with a value for the user-agent
header are allowed to access the given route. Your setup may look like the following code snippet:
server.route({
method: 'GET',
path: '/',
config: {
handler: …,
validate: {
headers: {
'user-agent': Joi.string().required()
},
options: {
allowUnknown: true
}
}
}
})
The important part is the config.validate.headers
object that needs to be set to the fields that you want to apply validation. You’d expect the user-agent
to be a string value and also force it to be required.
The additional options
object besides headers
softens the need to validate all fields that you might use. Without the option allowUnknown: true
, the validation process wouldn’t finish successfully when sending other header fields besides the user-agent
, because no other fields are allowed (by default).
The sending a basic GET
request to a hapi server with the route from above using Postman results in a response like this:
{
"statusCode": 400,
"error": "Bad Request",
"message": "\"cache-control\" is not allowed. \"postman-token\" is not allowed. \"accept\" is not allowed. \"host\" is not allowed. \"accept-encoding\" is not allowed. \"connection\" is not allowed",
"validation": {
"source": "headers",
"keys": [
"cache-control",
"postman-token",
"accept",
"host",
"accept-encoding",
"connection"
]
}
}
Especially for request header validation it’s beneficial to allow unknown properties, because you can’t have a proper validation rule in place for all the different options out there. Make sure to validate the headers that you’re using within your application and the rest is walking through your app without further notice.
Outlook
Within this tutorial, you’ve seen the setup to validate request headers on a given route. And besides the validation, you know how to allow unknown properties even though you’ve a single or multiple validation rules in place.
We’re happy to hear your thoughts and comments. Please don’t hesitate to use the comments below or find us on Twitter @futurestud_io. Let us know what you think!
Enjoy coding & make it rock!