This post kicks off a new series on hapi, a Node.js web services framework. Hapi provides a solid foundation that lets you fully focus on building your application by shipping with built-in support for plugins, authentication, caching, input validation, and many more essential features!
Honestly, we’ve build the entire Future Studio homepage using hapi and couldn’t be happier about the commitment to the hapi framework.
Throughout this series, you’ll learn about various functionalities provided by hapi or additional plugins. Actually, hapi’s plugin system is very powerful and you’ll recognize that there are many great plugins already available within the ecosystem.
You don’t need to invent the wheel as you go, just keep an eye on existing plugins that may provide your desired functionality. Anyway, we’ll get back to detailed hapi functionality later in this series.
The latest hapi version at the time of writing this tutorial is 16.6.2
. That’s the version this series will be based on and we’re going to update to newer versions when possible.
As already mentioned, this is a comprehensive tutorial series on hapi and the list below outlines available guides.
hapi Series Overview
- Get Your Server Up and Running
- v17 Upgrade Guide (Your Move to async/await)
- Become a Better Developer in 2018
- Become a Better Developer in 2017
- 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
Hapi Overview
Originally, hapi was developed at Walmart by a team around Eran Hammer with the idea that configuration is better than putting everything into code. Eran still leads the open source development of hapi itself and multiple plugins within the ecosystem. Up to this day, a great collection of plugins has emerged and they all add different functionality to the framework. The modularity of hapi allows to focus on core functionality and separating features like view rendering into an extra plugin.
However, let’s stop the hapi basics for now and get our hands dirty by creating a new hapi server that serves the “hello world” message.
Examples Are Available on GitHub
We’ll provide code examples for selected posts of this series on GitHub within the fs-opensource/nodejs-tutorials-hapi repository. Of course, you’ll find code snippets for individual functions within the related blog posts as well!
Your First “Hello World” Server
In the following, you’ll create a shiny new hapi server. Create a new project folder myhapiproject
on your machine that will contain the required files.
Preparations
Within this series, we’ll use NPM as a package manager to add dependencies with ease. To initialize a fresh NPM project, use npm init
and provide the asked information. You can just stay with the default values and edit the information later within the created package.json
file.
npm init
Having the package.json
file available, you can add hapi as a project dependency by installing the package and also save it as a dependency for your project (save hapi as a dependency by adding -S
to npm install
)
npm install -S hapi
That’s all you need. You’re ready to create and spin up your first hapi server.
Your First Hapi Server
A very basic server implementation is shown in the code snippet below. First, you need to require
the hapi
module and initialize a new Hapi.Server()
. Afterwards, add connection details by providing host
and port
information. Besides host and post, you can also define a Unix socket file or Windows named pipe.
Actually, that’s everything you need to spin up a very basic hapi server. Put the code below into a server.js
file.
server.js
var Hapi = require('hapi')
// create a server with a host and port
var server = new Hapi.Server({
host: 'localhost',
port: 3000
})
async function start () {
// start your server
try {
await server.start()
} catch (err) {
console.error(err)
process.exit(1)
}
console.log('Server running at: ', server.info.uri)
}
start()
The downside, you have only the command line output as visual evidence that everything went smoothly when starting the server.js
file. There aren’t any routes that can be called from the browser. And that’s exactly what we’ll add in the section below!
Routes
The simple server above just doesn’t serve any information and we should add a route that responds to a request. Add a route that just serves a friendly Hello Future Studio!
message when requesting your server via the browser, cURL, etc.
// add “hello world” route
server.route({
method: 'GET',
path: '/',
handler: (request, h) => {
return 'Hello Future Studio!'
}
})
Use the server
instance and add any desired route using the route()
method. The method
property can be any valid HTTP method and path
defines the endpoint URL for this route. Define your desired functionality within the handler
function, where you’ve access to the request
and response (called reply
) objects.
Routes support query and path parameters as well. We’ll go in detail on route parameters in a later tutorial. For now, let’s just focus on how to define a route in general.
The complete server code should look like this:
server.js
var Hapi = require('hapi')
// create new server instance
var server = new Hapi.Server({
host: 'localhost',
port: 3000
})
// add “hello world” route
server.route({
method: 'GET',
path: '/',
handler: (request, h) => {
return 'Hello Future Studio!'
}
})
async function start () {
// start your server
try {
await server.start()
} catch (err) {
console.error(err)
process.exit(1)
}
console.log('Server running at: ', server.info.uri)
}
start()
Start the updated server.js
file using node server.js
and open your browser. Navigate to localhost:3000
to see the Hello Future Studio!
message.
You’ve made it, your first hapi server is up and running serving your hello world message. Awesome!
Outlook
This tutorial helps you to get going on hapi and provided basic information about the framework. You’ve created a hapi server from scratch and added a route to serve a hello world message.
That’s a great start to proceed on. Within the upcoming post, you’ll learn how to add routes and handle incoming traffic in hapi.
Enjoy coding & make it rock!