Hapi on Steroids - Using Generator Functions with Hapi

You may be familiar with our Koa tutorial series: we took a look on how generator functions work and how you can do a basic application using Koa.

Also, we are huge fans of hapi - if you haven't seen our hapi node.js tutorial, now is the time!

So the question came: wouldn't it be great if we could use generator functions with hapi?

The Motivation

Using error-first callbacks fetching users from your database may look like something like this:

    age: 32
}, function (err, users) {
    if (err) {
        return reply(boom.badImplementation());

    return reply(users);

The same logic with hapi on steroids looks like this:

var users;

try {  
  users = yield Users.find({age: 32})    
} catch (exception) {
    return reply(boom.badImplementation());

return reply(users);  

How to Use Generators With Hapi

In short: we wrapped all of the route handlers with co in hapi. It is just a thin layer, but it enables you to write all your underlying logic using generators.

var co = require('co');

function get (request, reply) {  
  co(function* () {
    return yield db.getUsers();
    .then(function (response) {
    .catch(function (err) {
      return reply(boom.badImplementation());

module.exports.get = get;  


You may ask: okay, okay, but how to test it, I am used to hapi.inject? Gladly the solution is pretty easy. If you are using co-mocha you can do something like this in your before hook:

before(function () {  
  var _this = this;

  _this.server = yield server.create();

  this.inject = function (options) {
    return new Promise(function (resolve) {
      _this.server.inject(options, function (res) {
        return resolve(res);

With this solution, a test for an endpoint will become this:

describe('GET /v1/info', function () {  
  it('should return with a proper status code and body', function* () {
    var res = yield this.inject({
      method: 'GET',
      url: '/v1/info'

      status: 'ok'

The future

It is great to see more and more ES6 features landing in either Node.js or io.js. With tools like Babel one can use an either bigger set of language features.

We are curious to hear your stories on how you use ES6 in production today, what problems you are facing - don't hesitate to comment! :)

Getting Started with Hapi 8

hapi framework

A rich framework for building applications and services

hapi enables developers to focus on writing reusable application logic instead of spending time building infrastructure.

hapi is currectly being used by companies like Walmart (not just used but actively developed and maintained), Yahoo, PayPal or Mozilla - even the new npmjs website is built using it.

Starting your first server

Before dive into it, make sure that your are using version 8 of hapi, as some API calls are different in previous versions.

Installing hapi

You can grab the latest version of hapi from NPM:

npm install hapi --save  

Launch the hapi-ness

Let's take a closer look on what is happening here!

  • First, we create a new hapi instance.
  • Then our connection is defined - it is important, because in hapi you can define more, not just one. It can be useful when you want to create an API and a Web app as well in the same project, one listening on port 8001, the other one on port 8002.
  • The third step was to define a route handler. A route handler has a request and a reply argument, the first one contains information on the incoming request, while with the reply we can tell hapi how to respond to them.
  • Lastly, we start our server with server.start

Diving deeper

To be able to use hapi's full power we have to understand some of the key features/mechanisms of hapi:

  • lifecycle of a request
  • plugins
  • server methods

Lifecycle of a request

hapi enables us a very granular control over incoming requests. The following happens to an incoming request:

Hapi request lifecycle

We can modify each request at the extension points, using server.ext(). Let's take a look at an example when we want to set a new request path values on all the incoming requests:


In hapi plugins make it really easy to break your application up into isolated small applications with seperate business logic. Ideally all your application code goes to plugins, your server should only provide configuration to them.

Writing a plugin

Writing plugins is very simple - you only have to implement a register function with the following signature: function (server, options, next):

Register takes three arguments: server, options and next. server is a reference to our server instance, so here we can add route handlers as well, or access server methods that will be discussed later on. The options is a plain JavaScript object that the user passes to the plugin. After all done configuration is done we have to call next to signal hapi once we have finished registering our plugin - this can be useful also if you do some async operation in your application's bootstrapping phase.

Load plugings

To be able to use the previously created plugin we only have to load it and start the server:

Easy, huh? :)

If you want to register more plugins at the same time, then you can pass an array of plugins to the server.register.


If you want to pass a configuration to the server and want to access it in every plugin you can do the following when creating a hapi server:

After that this configuration object will be accessible on the server object using server.settings.app - yes, even in your plugins!

Server methods

Server methods can be used to share functions by attaching them to the server instance. You can add a server methods like this:

Later on this function can be accessed on the server object using server.methods.twitter.fetch - again, in your plugins as well, as you can register server methods in plugins too!


The features and mechanisms covered in this post hopefully get you interested in start using hapi.

For a complete API reference check out the GitHub repository.

Check out our guide: learn how to use generator functions with Hapi.