HTTP/2 server-push for hapi
Lead Maintainer - Devin Ivy
npm install underdog
See also the API Reference
Underdog is intended for use with hapi v19+ and nodejs v12+ (see v4 for lower support).
This module is currently under ad hoc maintenance, which means it relies fully on community support.
Underdog brings HTTP/2 server-push to hapi. The way it works is that you specify paths to resources that you'd like to push alongside a particular response. This is achieved with a call to the response toolkit decoration h.push()
. Before hapi responds to the original request, those push-requests will be made internally and their results will be streamed to the client as push-responses. Even pushed resources can specify additional resources to push. You can't make this stuff up!
const Fs = require('fs');
const Http2 = require('http2');
const Hapi = require('@hapi/hapi');
const Underdog = require('underdog');
(async () => {
const listener = Http2.createSecureServer({
// See tests for a key/cert that you can use to try this out
key: Fs.readFileSync(`${__dirname}/localhost.key`),
cert: Fs.readFileSync(`${__dirname}/localhost.cert`)
});
const server = Hapi.server({
listener,
tls: true,
port: 3000
});
await server.register(Underdog);
server.route([
{
method: 'get',
path: '/',
handler: (request, h) => {
const response = h.response('<script src="/push-me.js"></script>');
h.push(response, 'push-me.js');
return response;
}
},
{
method: 'get',
path: '/push-me.js',
handler: (request) => {
return 'document.write(\'I was definitely pushed!\');';
},
// To demonstrate that it must have been pushed, not requested directly
config: { isInternal: true }
}
]);
await server.start();
console.log(`Check-out ${server.info.uri} in your favorite HTTP/2-supporting client`);
})();
Underdog is compatible with nodejs's Http2Server
and Http2SecureServer
under the Compatibility API. Using any other HTTP server will simply disable server-push; h.push()
will no-op and return { response, allowed: false }
and h.pushAllowed()
will return false
.