Hapi.js
Overview

As they say on their website
Concepts
Before reading
The following slides include Hapi mechanics you should consider first before reading code samples.
For progressive understanding of the concepts and samples, please prefer reading this up to date documentation instead of the official site guides.
We'll skip on purpose the views and rendering part since we only care about building bridges between endpoints and services.
Hapi ecosystem
- Hapi has created its own ecosystem
- Hapi well known contributions are most of the time cleverly written
- If you reach an issue, first think it has been addressed by the community
High level mechanic
- A hapi server is object with an API letting you configure/declare
- auth
- cache
- methods (own cache)
- routes (own auth, cache + prerequisites, validation)
-
A hapi server registers plugins to
- decorate server, request or reply
- listen to events
- hook lifecycles
- A hapi server is bound to connections for listening
- Routes are set per { server, connection(s) } binding
Mid level mechanic
- Requests and responses have an exposed lifecycle
- The server is an EventEmitter (podium) (no behavior control)
- The server exposes an extension API (behavior control)
- Server constructor accepts default config for behaviors
- Server API overrides config and activates behaviors
Playing with the lifecycle
Playing with the configuration
Low level mechanic
- Hapi idiomatic decoration via plugins is to be prefered against manual injection, which includes
- server context
- request context
- per request context
- reply behaviors
- Same for events listening and lifecycle hooking
Reply API is confusing at first. The reply function understands values, buffers, streams, promises.
Decoration
Reply
Basic usage
Server
const Hapi = require('hapi');
const server = new Hapi.Server();const Hapi = require('hapi');
const CatboxRedis = require('catbox-redis');
const server = new Hapi.Server({
cache: CatboxRedis,
connections: {
load: {
maxHeapUsedBytes: 2e8, // bytes
maxEventLoopDelay: 20 // ms
}
},
useDomains: false
});with some options
The simplest instantiation
Connections
const abcServer = server.connection({
port: 3000,
labels: ['a', 'b', 'c']
});const abcServer = server.select(['a']);Retrievable by label
Auth
const HapiAuthBasicPlugin = require('hapi-auth-basic');
server.register(HapiAuthBasicPlugin); // register 'basic' scheme
server.auth.strategy('simple', 'basic', {
validateFunc: (request, username, password, callback) => {
callback(null, true, someUser);
}
});
server.route({ method: 'GET', path: '/', config: { auth: 'simple' } });Basic
server.auth.scheme('custom', (server, options) => ({
authenticate: (request, reply) => {
reply.continue({ credentials: someUser });
}
}));
server.auth.strategy('default', 'custom');Custom
State management
State management
- It's all about cookies
- It can use configured cache for persistence
Routes
Route configuration
server.route({
method: 'GET',
path: '/user/{userId}',
config: {
auth: 'default',
cache: { expiresIn: 5000 },
ext: {
onPreHandler: (request, reply) => { reply.continue(); }
},
validate: {
params: {
userId: Joi.string().required()
}
},
handler: (request, reply) => reply(fetchUser(request.params.userId)
}
});Warning: no nested route system included
Validation
Validation with Joi
const schema = Joi.object().keys({
username: Joi.string().alphanum().min(3).max(30).required(),
password: Joi.string().regex(/^[a-zA-Z0-9]{3,30}$/),
access_token: [Joi.string(), Joi.number()],
birthyear: Joi.number().integer().min(1900).max(2013),
email: Joi.string().email()
}).with('username', 'birthyear').without('password', 'access_token');Hapi has several places you can provide a Joi schema (at least an object with a validate function)
Here is a sample
But the best is to visit their documentation
Tests
Request injection
The simplest case
server.route({
method: 'GET',
path: '/',
handler: (request, reply) => reply(42)
});
server.inject('/').should.become(42);Exercises
Exercises
start a simple server with a single route
request it with a postman (or what you prefer)
instrument it to get the time spent in the handlers
Of course, keep helping yourself with the documentation: https://github.com/hapijs/hapi/blob/master/API.md
?
Hapi
By Alexis Tondelier
Hapi
Hapi.js main concepts
- 871