Within previous tutorials throughout this hapi series, you’ve seen a lot functionality related to the server itself, requests and authentication. This guide is the first one geared towards responses and precisely shows you how to set the response status code that follows the RFC.
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”
- How to Reply a JSON Response
- How to Set Response Status Code
- How to Handle 404 Responses for Missing Routes
- 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
Hapi Default: 200 OK
By default, hapi uses the 200 OK
status for non-error responses that are created using the reply
interface. Usually, that’s absolutely fine and your consuming clients will work properly. Nonetheless, there are situations where you want to provide more precise status codes, like when creating new documents (201 Created
) within your database or in error scenarios. Let’s jump right into the topic and have a look on how to set your desired status code for responses.
Set Response Status Code
Using the reply
interface with a usual JavaScript object will create a response that can be further customized. The interesting part is the .code(code)
method that adjusts the response’s status.
hapi v17
server.route({
method: 'GET',
path: '/',
config: {
handler: (request, h) => {
const data = { key: 'value' }
return h.response(data).code(201)
}
}
})
hapi v16
server.route({
method: 'GET',
path: '/',
config: {
handler: (request, reply) => {
const data = { key: 'value' }
reply(data).code(201)
}
}
})
Let’s assume a client sends a request with payload and you’ve created a new object within the database based on the client’s information. Now you want to indicate that the request was handled successfully by using the response status code 201 Created
and as payload you’re sending the newly created object.
The code snippet above mainly illustrates the response creation with the help of reply
and afterwards updates the status code to 201
. Actually, that’s all you need to do when setting your status code of choice.
Error Status Codes with Boom
Hapi allows you to benefit from their library that creates HTTP-friendly error objects: called Boom. With the help of boom
, you’re creating consistent error objects with correct HTTP status codes. Furthermore, you can add and send a custom error message with more specific information about the problem you’ve encountered while processing the request.
Using a boom
error object as the response will automatically set the response status code. boom
provides methods to easily create the response object for each HTTP status equal to 400
and above.
hapi v17
const Boom = require('boom')
server.route({
method: 'GET',
path: '/',
config: {
handler: function (request, h) {
throw Boom.notFound('Cannot find the requested page')
}
}
})
hapi v16
const Boom = require('boom')
server.route({
method: 'GET',
path: '/',
config: {
handler: function (request, reply) {
reply(Boom.notFound('Cannot find the requested page'))
}
}
})
The example above leverages the .notFound(message)
method of boom
to create a 404 Not Found
response. The custom message will be sent within the response payload. The response that is received on client side looks like this:
404 Not Found
{
"statusCode": 404,
"error": "Not Found",
"message": "Cannot find the requested page"
}
The statusCode
and error
are available within the payload as well as your custom message
.
Status Codes for Empty Response Payload
In situations where you don’t send any payload to your client, the 204 No Content
status code is the correct choice. Actually, there are many clients (even browsers) that wait for status 200 OK
in case the request was processed properly. That’s why hapi manages the balancing act of setting 200 OK
as the default response status.
If you want to comply the RFC and send 204 No Content
in situations where your response doesn’t contain any payload, configure your route to use the 204
status:
hapi v17
server.route({
method: 'GET',
path: '/',
config: {
response: {
emptyStatusCode: 204
},
handler: (request, h) => {}
}
})
hapi v16
server.route({
method: 'GET',
path: '/',
config: {
response: {
emptyStatusCode: 204
},
handler: function (request, reply) {
reply()
}
}
})
The example above illustrates a response without any payload and a 204 No Content
status code.
In case you provide data to reply
, hapi will use the proper 200
or any (error) code you defined for the response. Of course, you can also use reply().code(204)
to send empty responses with a precise status code and skip the extra route configuration.
Outlook
Hopefully this guide helps and motivates you to set proper status codes within your future coding sessions. Actually, clients will benefit a lot from precise responses including status codes other than just 200
and 400
. Especially in error situations you’re able to display detailed messages on what needs to be fixed to successfully request a resource.
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
- Boom — HTTP-friendly error objects
- HTTP status codes