How to reply JSON and JSONP in Hapi


hapi json jsonp nodejs Tutorials

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 :

server.route({
    method: 'GET',
    path: '/index',
    options: {
        handler: async (req, reply) => {

            let obj = {
                name: 'Roman',
                age: 24
            };

            return reply(obj);
        }
    }
});

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:

server.route({
    method: 'GET',
    path: '/index',
    options: {
        handler: async (req, h) => {

            let obj = {
                name: 'Roman',
                age: 24
            }

            return h.response(obj);
        }
    }
});

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

server.route({
    method: 'GET',
    path: '/index',
    options: {
        handler: async (req, h) => {

            let obj = {
                name: 'Roman',
                age: 24
            }

            return obj;
        }
    }
});

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

Hapi JSON response

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:

server.route({
    method: 'GET',
    path: '/index',

    options: {
        json: {
            space: 10,
            suffix: 'after'
        },
        handler: async (req, h) => {

            let obj = {
                name: 'Roman',
                age: 24

            }
            return h.response(obj);
        }
    }

});

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

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.

server.route({
    method: 'GET',
    path: '/index',
    options: {
        jsonp: 'callback',
        handler: async (req, h) => {

            let obj = {
                name: 'Roman',
                age: 24

            }
            return h.response(obj);
        }
    }
});

The example of work:

Hapi sends JSONP with result

Headers of response

Learning Hapi.js? Buy my Hapi.js Handbook🔥

comments powered by Disqus