Serving static files with inert

inert (https://github.com/hapijs/inert) is the static file and directory handler module for hapi. It provides a lot of useful utilities for simplifying serving static content. Let's look at one of those now:

const Path = require('path');
const Hapi = require('hapi');
const Inert = require('inert');                    // [1]
const server = new Hapi.Server();
server.connection({ port: 3000 });
server.register(Inert, (err) => {                  // [2]
  server.route({
    method: 'GET',
    path: '/{param*}',
    handler: {                                     // [3]
      directory: {                                 // [3]
        path: Path.join(__dirname, 'public'),      // [3]
        listing: true                              // [3]
      }                                            // [3]
    }                                              // [3]
  });
  server.start((err) => {
    console.log(`Server running at: ${server.info.uri}`);
  });
});

Hopefully, this example is quite readable, and you begin to see the power of hapi's configuration-centric approach come into play here. Can you guess what this is before I explain the code? With reference to the numbers in the preceding code, let's go through it now line by line:

  • [1]: First we require the inert module. You will need to run npm install if you are trying out this example.
  • [2]: We register the inert plugin to the server.
  • [3]: This is the new functionality inert has provided: a custom directory handler. Here we provide a directory configuration object which specifies the path to directory we plan to server static files from. In this example, the directory we serve content from is the public directory.

If you haven't figured it out yet, what we have built here is a static file server. Not bad for 25 lines of code! We also get to take advantage of the added security of hapi and inert here. A request to this route can only access files inside the public folder. Without this, an attacker could access files like the source code to this application, or worse, password files on the OS that this is running on—this is commonly referred to as a Directory Traversal Attack.

This is an example of the type of protection hapi offers out of the box when we say it is secure by default. Without knowing this type of security exploit, you are still guarded against it. This route will also return a 404 error if the file is not found, so you don't have to. Along with the directory handler, there is a custom file handler that works much like the aforesaid, but only serves a single file for a request instead of the files from a directory; it can be used as follows, something like a call-all not found route:

…
server.route({
  method: 'GET',
  path: '/{param*}',
  handler: {
    file: '404.html'
  }
});
…

inert also provides a decorated reply, reply.file(). This is useful when you need more granular control when serving files. Let's say, for example, if you only wanted to serve the HTML files from a directory from a certain handler, you could do something like the following:

…
server.route({
  method: 'GET',
  path: '/{file*}',
  handler: function (request, reply) {
    const path = `${request.params.file}.html`;
    return reply.file(path);
  }
});
…

Note that this doesn't give you directory traversal protection like the previous directory handler, so be aware that you will need to provide this yourself when using reply.file().

inert and hapi are very good at providing a lot of flexibility in working with static content. Let's look at combining inert and what we have learned about the hapi request life cycle to build a website that serves HTML pages, static images, and has a custom 404 page for bad links:

const Path = require('path');
const Hapi = require('hapi');
const Inert = require('inert');
const server = new Hapi.Server();
server.connection({ port: 80 });
server.register(Inert, (err) => {
  // serve static html and image files
  server.route({
    method: 'GET',
    path: '/{files*}',
    handler: {
     directory: {
       path: __dirname
     }
    }
  });

  // return not found page if handler returns a 404
  server.ext('onPostHandler', function (request, reply) {
    const response = request.response;
    if (response.isBoom && response.output.statusCode === 404) {
      return reply.file('./404.html').code(404);
    }
    return reply.continue();
  });

  server.start((err) => {
    console.log(`Server running at: ${server.info.uri}`);
  });
});

Hopefully, by now this is all starting to look familiar to you, as no new concepts have been introduced here. The addition here to the previous examples was the addition of an extension point on onPostHandler, which checks the response of the handler in the life cycle of the request. If the directory handler returned a 404, this extension point returns a 404 HTML page instead of a boom error object, else it continues with the request life cycle.

This covers most of what you need to know in terms of serving static content. If you would like to know more, I would encourage you to read more of the inert module documentation and source code, which is fortunately quite small.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.184.102