building an api in node with hapijs
TRANSCRIPT
Building an API
in Node with HapiJSSoCal Code Camp . Cal State Fullerton . March 7, 2015
Loc Nguyen
require('selfie');
• Ruby, JavaScript, C#, Java….PHP. New to Node!
• API & microservice planning, UI architecture
• locnguyen.com
• @locn
AngularJS-OC
http://meetup.com/AngularJS-OC
Agenda
• What is HapiJS
• Creating an API server
• Configuring routes
• Requesting handling
• Data validation
• Plug-ins
• Securing the API
• Server side caching
• Client side caching
What is HapiJS?
• Yet another NodeJS web framework
• Not as much mindshare as Express
• Built with developer scalability in mind
• Built by Walmart Labs and Eran Hamme
• Configuration over code
The server
1. npm init
2. npm install --save hapi nodemon
The server
var Hapi = require('hapi');
var server = new Hapi.Server();
server.connection({ port: 9000 });
server.start(function () {
console.log('Server available at %s',
server.info.uri);
});
Cool Server things
var Hapi = require('hapi');
var server = new Hapi.Server();
var c = server.connection({
port: 9000, labels: ['core'] });
var a = server.connection({
port: 3000, labels: ['admin'] });
server.start(function () {
console.log('Core available at %s’, c.info.uri);
console.log('Admin available at %s’, a.info.uri);
});
Configuring routes
server.route({
path: '/product/{id}',
method: 'GET',
handler: function (request, reply) {
reply('Sup dawg');
}
});
Request handling
server.route({
path: '/product/{id}',
method: 'GET',
handler: function (request, reply) {
var prodId = request.params.id;
console.log('Product id: %s', prodId);
console.log('Include reviews: %s',
request.query.includeReviews);
reply({ id: prodId });
}
});
• Demo
Request handling
server.route({
path: '/login',
method: 'POST',
handler: function (request, reply) {
var json = request.payload;
console.log(json.email, json.password);
reply('Nope!').status(401);
}
});
• Demo
Data Validation
• Done declaratively with object schema definition
• Joi framework – https://github.com/hapijs/joi
• Simple value validations
• Regex
• Array of valid values
• Conditional
• Demo
Plugins
• Plugins allow complete isolation of logic
• Configurable per labeled server
• Just register on the server
server.register([{
register: require('./fooPlugin'),
options: {
bar: 'hello'
}
}]);
• Demo
Securing the API
• It depends...everyone’s scheme is different
• Accomplished via plugins
• Flexible, can be configured per route
• See http://hapijs.com/tutorials/auth
server.register(require('hapi-auth-jwt'), function (err) {
server.auth.strategy('token', 'jwt', 'required', {
key: server.settings.app.jwtSecret
});
});
Server side caching
• Comes with in-memory cache for local development
and testing
• Supports a variety of solutions
1. memcached
2. Mongodb
3. Riak
4. Redis
Server side caching
• In-memory is the default
• Can configure multiple types of caches
• Hapi talks to caches via Catbox abstraction
• Caching services implement strategy, e.g. catbox-
redis
• Set up caches when creating a Hapi server
• Example and demo
Server side caching
var server = new Hapi.Server({
cache: [{
name: 'fooRedisCache'
engine: require('catbox-redis'),
host: '127.0.0.1',
port: 6379
partition: 'cache'
}]
});
Client side caching
• Support built in for HTTP caching headers
• Cache-Control
• Last-Modified
• E-Tag
• Examples
Client side caching
server.route({
…
config: {
cache: {
expiresIn: 1000 * 60 * 60 // 1
hour
}
}
});
Client side caching
var doc = { … };
reply(doc).header('Last-Modified', new
Date().toUTCString());
reply(doc).etag(docChecksum);
• Demo
fin
● Hapi makes it easy to not build a monolith
● Simple to separate business logic from web plumbing
● Plugin architecture makes it easy to swap in changes
(or add more)
Thanks!
Questions?
[email protected], @locn, locnguyen.com
Further topics:
● Logging
● Testing
● Proxies
● View engines
● Request lifecycle