Using Good plugin to log in Hapi

To add logging in our Hapi-based application we will use a good-plugin. It’s official plugin from Hapi plugins ecosystem. Good plugin used to report and monitor Hapi server events. In this tutorial, I want to show you how to log to file, to console and to API-endpoints using¬†good-plugin.

Getting started

Let’s go to an existing Hapi project folder and create our server file:

We can install the good and good-squeeze plugins using the following in the terminal:

Log to console

Let’s create an options object, where we will set the interval of logging and how we will log:

Every second we will log information about our server status and i/o requests, responses to terminal console. But at the beginning, we have to register the Good plugin and options configuration, before our server starts:

When you run the server and make some requests to /index or /about route, you should see the next in console:

Loggin in console in Hapi
Logging in console in Hapi

If we need only to log and response events, we should install the good-squeeze  plugin:

And push the next object to options.reporters.console array:

The full configuration will look like this:

Log to file

To save logs to file we should install the another Good plugin – good-file:

To save every request and response log we can use the next configuration:

Every request log or response log object will be saved to ./logs/server_log file.

Log to another API-endpoint

To logging to another API-endpoint, we should install the good-http plugin:

We can use the following configuration inside options object, if we want to stream logs to another API endpoint. It’s very useful for debugging.

This logger will be send the errors, log, response objects to http://production.somesite.com:5000 with certain data.

You can read more details on  https://github.com/hapijs/good/blob/master/API.md#reporter-interface, about using the reporter interface.

Learning Hapi.js? Buy my Hapi.js HandbookūüĒ•

How to use Pug with Hapi

This tutorial is compatible with hapi v17. Node and Hapi should be installed for work with this tutorial.

In this quick post I will show how to use a Pug as a default template engine in your Hapi project. We will use information from previous article about how to use handlebars in Hapi. First of all, let’s install the Pug:

Setup template engine and render

You need include it to your server and initialize the default template engine for our server. Use the following code:

Now, we can start creating a new views. Create an index.html file in templates folder with the following content:

As you see, we added dynamic content –¬†title¬†and¬†message. We will interpolate these variables inside¬†GET /index¬†route using the¬†view¬†method:

Full example

You can check more information about how to use Pug in the official guide.

Learning Hapi.js? Buy my Hapi.js HandbookūüĒ•

How to reply JSON and JSONP in Hapi

This tutorial is compatible with hapi v17. Node and Hapi should be installed for work with this tutorial.

Using JSON

We can always manually set headers and convert our object to JSON using JSON.stringify, but Hapi provides a method which is used to simplify this routine.
In Hapi v16 we used the .reply  method in the route handler. This method converts pure Javascript object to JSON string and sends it to client with the correct content-type Рapplication/json :

In v17 the .reply has been replaced by .h interface with helpers. Now we should use the .response method of .h to send JSON in Hapi framework. An example:

Or even can send only pure Javascript object. It will be automatically converted:

If you open the Postman, you will see the correct result and headers:

Hapi JSON response
Hapi JSON response – result
Hapi JSON response - headers
Hapi JSON response – headers

But not all values will be converted to JSON. Here the list what content-types will be shown on client for different types of data:

  • .h.response(true)¬†–¬†content-type –¬†application/json; charset=utf-8
  • .h.response(false)¬†–¬†content-type –¬†application/json; charset=utf-8
  • .h.response(1954)¬†–¬†content-type –¬†application/json; charset=utf-8
  • .h.response('1954')¬†–¬†content-type – text/html; charset=utf-8
  • .h.response(new Date()¬†–¬†content-type –¬†application/json; charset=utf-8
  • .h.response([1,2,3])¬†–¬†content-type –¬†application/json; charset=utf-8
  • .h.response(null)¬†– no¬†content-type
  • .h.response(undefined)¬†– no¬†content-type
  • .h.response({'field':'name'})¬†–¬†application/json; charset=utf-8
  • .h.response(null)¬†– no¬†content-type
  • .h.response(Math.abs)¬†– no¬†content-type

If you look deeper, Hapi detects when it sends pure Javascript object and convert it using JSON.stringify method and adds a correct content-type. We can pass an additional parameters to JSON.stringify method using the json property in options object of route. The json object supports the following properties:

  • space¬†– the number from 0 to 10 to indent space in nested objects.
  • replacer¬†– either an array or function used to convert the result and it’s called for each item.
  • escape¬†– the boolean, default false. When¬†true¬†it calls¬†Hoek.jsonEscape()¬†when conversion to JSON is finished.
  • suffix¬†– the string, default¬†no suffix. This suffix appended to JSON string after conversion.

How to send JSON with custom space and suffix, you can check in the following example:

When you check your browser on this route, you will see that JSON looks different:

Using JSON configs in Hapi route
Using JSON configs in Hapi route

Using JSONP

JSONP it’s¬†JSON with a padding. To enable support of JSONP we need to set¬†jsonp¬†property in¬†options¬†object of route. The jsonp property will contain a name of query parameter with the name of function. For example, if client will send¬†callback=handler¬†the response will come¬†handler({...}). Unlike JSON content-type, JSONP will come with¬†text/javascript; charset=utf-8.¬†¬†If we set only¬†jsonp¬†property, we can use this route to get both JSON and JSONP response, just send an additional query parameter, if you want to get JSONP.

The example of work:

Hapi sends JSONP with result
Hapi sends JSONP with result
Headers of response
Headers of response

Learning Hapi.js? Buy my Hapi.js HandbookūüĒ•

Getting Started With Swagger and Hapi

If you want to create a documentation for API in your Hapi project, you can use the Swagger. Swagger is open-source tool to create documentation for REST API services.

I already told how to create a simple REST API with Hapi, so we will continue with an existing code.

Adding Swagger to Hapi project

The most popular library for Hapi framework its hapi-swagger. We can install it using the following:

Because, the hapi-swagger will generate a documentation as HTML files for our API, we need install some important Hapi plugins:

Configuring Swagger options

First of all, you need to import the hapi-swagger, vision and inert modules to index.js:

and create a configuration object for Swagger. It will contain the name of our documentation and the version number, we want to specify:

After all these actions, we need to register (before server starts) all plugins and Swagger configuration. We can do this using the ‘register’ method of server instance:

Adding description, tags, notes to API routes

We are one step away from testing. Now we can add description, tags, notes to our routes. The¬†tags¬†property is the simplest way to structure your API documentation in Swagger. Let’s take one route, for example GET /books¬†and add more information what is it doing for client:

Using the example above, do the same with other POST/PUT/DELETE routes.

Testing documentation

When you start your server in the terminal using the:

the hapi-swagger plugin will generate a new page for documentation. By default – /documentation. In our case –¬†localhost:3000/documentation

When you open the browser on this page, you will see the beautifully structured documentation. For me, the browser shows the following:

Swagger API doc in Hapi project
Swagger API doc in Hapi project

You can even test your api:

Open the route and test it in your Hapi project
Open the route and test it in your Hapi project

Learning Hapi.js? Buy my Hapi.js HandbookūüĒ•

Creating a simple REST API with Node and Hapi in 10 min

In this tutorial we will create a simple REST API using the Node and Hapi framework. We will create a simple server with API which returns the books data and allow us to create, update and delete books.

Getting started

To follow this tutorial you should have the basic fundamentals of using command line.
All the following was done with the next requirements: Node v9.10.0, Hapi v17.8.1

Set up the project

Create a new folder and initialize a new project using the next command:

Then install Hapi framework with plugins, FS module to read/write data and Util module:

Now we can create the main file for our server. Let’s call it index.js and add the following code of very basic server:

Adding data

In our app we will use the JSON file as a main data store. Create a new books.json file in project folder and paste the next data:

We will make manipulations with this file on server, when the client makes the GET, POST, PUT, DELETE requests.

Getting list of books

Let’s create our first REST API endpoint to get the list of books. Add the following code in¬†index.js file:

In the “handler” method we read the data from¬†books.json file using the “readFile” function, then parse it using “JSON.parse” and send using the “.response” method. We need to parse this data, because the books variable it’s a string (JSON) and the server will send it as HTML text, but if “.response” method will take the pure javascript object, it sets all headers correctly. In this case client will understand that this is JSON.

When you access defined API route using GET http://localhost:3000/books you will get the list of all books frombooks.json file.

Creating a new book

To create a new book we need to define a POST /books route:

Inside handler, we setting the received data from client to book variable. Then reading the books data, setting a simple identifier and push a new book to books array. After all these actions, we rewriting the books.json and send an updated array of books to the client.

For example, if we make a POST request to /books endpoint with the next data:

Server will returns the next result:

Updating an existing book

In this section we will update an existing book by ID. We will send the book ID as a query params and new book data in request payload. Add the following code toindex.js:

The¬†request.params.id¬†it’s ID from path. We using it to look an existing book in the books array. When we find it, we update it.

For example, if we make a PUT request to /books/1 endpoint with the next data:

Server will produce the next result:

Deleting an existing book

To remove an existing book from our¬†books.json file, we will use the similar logic as we used in previous section. Let’s add the DELETE /books route to our server:

We filtering the existing array of books and exclude the book, which id we passed to our server. For example, if we make a DELETE request to /books/2 endpoint, we get the following result:

Full example

Conclusion

As you see, you can quickly create a basic REST API using the Hapi framework for 10 minutes. With this simple tutorial you can start to discover more complex topics like querying data from DB inside route handlers and sending to client, creating a separate folders for API routes, how to work with parameters or how to send files in your API.

Learning Hapi.js? Buy my Hapi.js HandbookūüĒ•