Menu Close

Server-Side Development with Hapi.js — Base64 and Errors

Hapi.js is a small Node framework for developing back end web apps.

In this article, we’ll look at how to create back end apps with Hapi.js.

Base64 Encoding

We can handle base64 encoding and decoding with the @hapi/b64 module.

For instance, we can write:

const Path = require('path');
const Hapi = require('@hapi/hapi');
const Fs = require('fs');
const B64 = require('@hapi/b64');

const init = async () => {
  const server = new Hapi.Server({
    port: 3000,
    host: '0.0.0.0',
    debug: { request: ['error'] }
  });

  server.route({
    method: 'GET',
    path: '/',
    handler(request, h) {
      const stream = Fs.createReadStream(Path.join(__dirname, 'package.json'));
      const encoder = new B64.Encoder();
      stream.pipe(encoder).pipe(process.stdout);
      return 'success'
    }
  });

  await server.start();
  console.log('Server running at:', server.info.uri);
};
process.on('unhandledRejection', (err) => {
  console.log(err);
  process.exit(1);
});
init();

We call Fs.createReadStream to create the srean.

Then we create the encoder object with the B64.Encoder constructor.

And then we pass the encoder to the stream.pipe method to encode the stream into a base64 string.

And then we pass that into stdout with another pipe call.

Base64 Decoding

We can decode base64 text into its original content with the @hapi/b64 module.

To do this, we write:

const Path = require('path');
const Hapi = require('@hapi/hapi');
const Fs = require('fs');
const B64 = require('@hapi/b64');

const init = async () => {
  const server = new Hapi.Server({
    port: 3000,
    host: '0.0.0.0',
    debug: { request: ['error'] }
  });

  server.route({
    method: 'GET',
    path: '/',
    handler(request, h) {
      const stream = Fs.createReadStream(Path.join(__dirname, 'encodedfile.b64'));
      const decoder = new B64.Decoder();
      stream.pipe(decoder).pipe(process.stdout);
      return 'success'
    }
  });

  await server.start();
  console.log('Server running at:', server.info.uri);
};
process.on('unhandledRejection', (err) => {
  console.log(err);
  process.exit(1);
});
init();

We call the Fs.createReadStream to create the read stream and read the file with the given path.

Then we create the decoder object with the B64.Decoder constructor.

And then we call stream.pipe with the decoder to do the decoding.

Then we call pipe again to pipe the decoded content to stdout .

Error Response

We can add a login route easily with the @hapi/boom module.

To use it, we write:

const Hapi = require('@hapi/hapi');
const Boom = require('@hapi/boom');

const init = async () => {
  const server = new Hapi.Server({
    port: 3000,
    host: '0.0.0.0'
  });

  server.route({
    method: 'GET',
    path: '/',
    handler(request, h) {
      throw Boom.badRequest('invalid query');
    }
  });

  await server.start();
  console.log('Server running at:', server.info.uri);
};
process.on('unhandledRejection', (err) => {
  console.log(err);
  process.exit(1);
});
init();

We call Boom.badRequest to create an Error object that we can throw.

It takes the error message as the argument.

Then we throw that and we should see:

{"statusCode":400,"error":"Bad Request","message":"invalid query"}

returned as the response.

We can check if an object is an instance of the Boom.Boom constructor by writing:

const Hapi = require('@hapi/hapi');
const Boom = require('@hapi/boom');

const init = async () => {
  const server = new Hapi.Server({
    port: 3000,
    host: '0.0.0.0'
  });

  server.route({
    method: 'GET',
    path: '/',
    handler(request, h) {
      const err = Boom.badRequest('invalid query');
      return Boom.isBoom(err);
    }
  });

  await server.start();
  console.log('Server running at:', server.info.uri);
};
process.on('unhandledRejection', (err) => {
  console.log(err);
  process.exit(1);
});
init();

We call Boom.isBoom to do the check.

It should return true since err is an instance of Boom.Boom .

Conclusion

We can return error responses easily with the @hapi/boom module.

The @hapi/base64 module lets us encode and decode base64 content.

Posted in Hapi