Mitchell Lee
Mitchell Lee

Reputation: 456

Hapijs Custom 500 Error Page

Looking through Hapi's documentation, and trying to google, I can find how to setup a 404 page, but I cannot find anything about setting up a 500 page.

I tried adding an error handler like follows:

server.on('internalError', function (request, err) {
    console.log("Internal Error:", err);
    request.reply.view('errors/500', {
        error: err
    }).code(500);
});

But my hook never gets called. Is there an easy way to return a custom 500 page with Hapijs?

Upvotes: 6

Views: 5373

Answers (2)

Eduardo Veras
Eduardo Veras

Reputation: 179

For those looking for this answer compatible with Hapi v17+, the same code index.js code will be translated as:

index.js

"use strict";

const hapi = require('hapi');
const path = require('path');

const server = new hapi.Server({ port: 4000 });

server.route({
    method: 'GET',
    path: '/',
    handler: (request, h) {
        return new Error('I\'ll be a 500');
    }
});

server.ext({
    type: 'onPreResponse',
    method: (request, h) => {

        if (request.response.isBoom) {
            const err = request.response;
            const errName = err.output.payload.error;
            const statusCode = err.output.payload.statusCode;

            return h.view('error', {
                statusCode: statusCode,
                errName: errName
            })
            .code(statusCode);
        }

        return h.continue;
    }
});


(async()=>{

    await server.register([ require('@hapi/vision') ]);

    server.views({
        engines: { hbs: require('handlebars') },
        path: Path.join(__dirname, 'templates')
    });

    await server.start();

    return `Server running at: ${server.info.uri}`;

})().then(console.log).catch(console.error);

Upvotes: 1

Matt Harrison
Matt Harrison

Reputation: 13567

You need to trap the error response inside an onPreResponse extension function and set a new HTML response there.

The same principle applies to any Boom error, whether it be one set by you in a handler or set by hapi internally (e.g. a 404 Not found or a 401 Unauthorized from failed auth.

Here's an example that you can try yourself:

index.js

const Hapi = require('hapi');
const Path = require('path');

const server = new Hapi.Server();
server.connection({ port: 4000 });

server.route({
    method: 'GET',
    path: '/',
    handler: function (request, reply) {

        reply(new Error('I\'ll be a 500'));
    }
});

server.ext('onPreResponse', (request, reply) => {

    if (request.response.isBoom) {
        const err = request.response;
        const errName = err.output.payload.error;
        const statusCode = err.output.payload.statusCode;

        return reply.view('error', {
            statusCode: statusCode,
            errName: errName
        })
        .code(statusCode);
    }

    reply.continue();
});


server.register(require('vision'), (err) => {

    if (err) {
        throw err;
    }

    server.views({
        engines: {
            hbs: require('handlebars')
        },
        path: Path.join(__dirname, 'templates')
    });

    server.start((err) => {

        if (err) {
            throw err;
        }

        console.log('Server running at:', server.info.uri);
    });
});

templates/error.hbs

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{title}}</title>

    <style>
        body {
            text-align: center;
            background: #B0B0B0;
            color: #222;
        }
        .error h1 {
            font-size: 80px;
            margin-bottom: 0;
        }
    </style>
</head>
<body>
    <div class="error">
        <h1>&#x26a0;<br/>{{statusCode}}</h1>
        <h2>{{errName}}</h2>
    </div>
</body>
</html>

Test it out by going to http://localhost:4000/ to see your custom error page:

enter image description here

This approach catches any Boom response, including those generated internally by hapi rather than by us. Therefore will also work with 4xx errors. Try navigating to http://localhost:4000/notapage and you'll get the same pretty page but for a 404:

enter image description here

Upvotes: 21

Related Questions