Node.js: HTTP/2 server setup

In  this tutorial we will check how to setup a very simple HTTP/2 server using node.js. We will be using the HTTP/2 module to setup the server and a web browser as client.

Introduction

In  this tutorial we will check how to setup a very simple HTTP/2 server using node.js. We will be using the HTTP/2 module to setup the server and a web browser as client. Upon receiving the request, the server will just return back a “Hello World” message to the client.

Note that you may need to update the node.js version for the HTTP/2 module to be available. I’ll be using version 11.6.0 of node.js.

One important thing to take in consideration is that currently no browser supports HTTP/2 without encryption [1][2], which means that we will need to configure our server to work over a secure connection (HTTPS).

This means that we will need to generate a testing server certificate (it will be self signed) and a private key. We will check how to do it on the next section.

The tests shown here were done on Windows 8.1.

Generating the certificates

Before generating the required certificate and private key, we need to install openssl. Only after that it will be possible to send the command needed to generate both. Explaining how to install openssl is outside of the scope of this post but there are plenty of sources available on the web that explain how to do it.

Once you install openssl, open a command line on your machine and send the command shown below. Note that this is the same command that is shown on the node.js HTTP/2 documentation server example.

openssl req -x509 -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost' -keyout localhost-privkey.pem -out localhost-cert.pem

After running the command, two files should have been created on the directory where you are located. They are named localhost-cert.pem and localhost-privkey.pem, as shown in figure 1.

Generating private key and self signed certificate with openssl

Figure 1 – Created certificate and key.

Alternatively, in case you find any problems while generating the files or installing openssl, below is the content of both files. You just need to copy the content of each one and save them in files with the names and the extensions indicated before.

localhost-privkey.pem

-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDL5zzcNTgRZgI5
5pykJJldlm/MiAuen9fC39MpBHMeyr7iMxUt2Lzsly0OBuZVMkssNbgAmUOEeiFm
uKypUxH5b6DI+8ipZBoZeaimj4/2Z7I0UYvAR1jF9afnv+2fyzVGtgkQWxx/DPXp
TVCFZHv78dIXttqOjNo0UcHKrbQpTywJa2NAXHWV20jvqU8Bvcq5Lefs/CAyngzN
lZ8B8InbI5/fqa5LkHz8OPsJPOMVA+1UfOmAY8KYLWRgatAHtyamLR+fW5KMHdL7
pLU+S+obTBgvhe7s8C0VwVkAUlyNTMJmL4tev07PXkyDFEbQITQp2HiiyQfeuCCN
XqsI4qorAgMBAAECggEBAKaXyiC8lo+YgY8e/LIbePZ+198K9Dtoq1b7mkGz8f6h
da3IQLCRmWHP7i68smm/Sq3XQfuzPPe69RlBH0jEpzXd30b2eC71q2FPBdz4BI40
kOOwEHdLk5tBpypwpEvfMisQxX0Ig9LGGxC/a19hBu+E1rsrWYwIRqtidOwMWds4
8BKDDPKts59DeEyKKCecj5pySN8T1fFgI6MSjcdrxSXkQrjxEZIo48a9RbBcenT8
ONd4vZeUnICHXhjSs8Ogd2e4oR3bE/aF9u1lE5RqRZ1Pw+tmoMxQBBwCFO3KEkCM
OtrSkhsfQs5I6t0RaoEVOy78aVYMVTxLxAhGAd8f8sECgYEA5JfCWmDlIwmRjINd
uVc+NNvrTRM0eBOGujBN2eWZ/2Bf/ZqZ2MPAIAUKsURN6v8ihgN728KIPp4xJ3rI
isD00hlxzjADdtAe7d3El9/rUaImxLFKiAR8X+hVuDjLXqws7OwX7f5feBSHnj+v
GTI/CxwMYNSS4ecqgKEh3rplBuECgYEA5Fmtlrorxqo4uivOfZXIlzP0fbCC8Zhh
a0Jx2m8nAB+Bvl3slzkdtMLj+EiBqU+jBYbcDZKgYO5QwPx7vM4kbVzDdgHpDP8R
rDYSe6I/3VOmtFFPysd1mhZXbHnBHoVyJZoUfjrD27HYyJ3IsUdstVtY74hhpkW6
TnzG+oO7rosCgYBSyoQhp6ZVokmM0qdHUUm+a0g1ihcexjOti4EmwfmcfJNHjo7Z
60vSTQEqYsq1qeIfF3Psi/A8fZ7f5aBsYKZK0dxeCRW4GniZPhDN0NOxpUDVTEDq
MnW5ZrRlHGzLxSAgTwH7uH1rSEQ2FGqefYxHwcjZ6SOpncfO/oz91hRxAQKBgFgf
88oTlwlYcAQJG+uDfqI7vsMy95XdRNtsDRxLgTWe8ydQgBnsRPaZr/kFomSBA10C
qrHiQFqoHiocRnSa6Zv7DMPiANqvJVbcl013VEZKHi/AoZaUW2JX9O08H7dzsJWq
XPZKH4QNoqfpnKYt9loXIr9uVqEgj8HyjafoZun5AoGAYpyJw70EOLbuddy2vnbo
e/5IOYinP9sdhiuVeNbjCpFOLWXwfmRO2f9ilOl1RQ/UhpYqNQ71CP+8eGS5YZQa
xmchCMCgtEwH0P2A3wdsVCQHAYuljk/yWdgsaY77gqYypEXV4f0s717ieIrEqzu5
2agFeeGfQ0hjCBSe4OPeuk4=
-----END PRIVATE KEY-----

localhost-cert.pem

-----BEGIN CERTIFICATE-----
MIIC+zCCAeOgAwIBAgIJAKIWZpKT7yqeMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
BAMTCWxvY2FsaG9zdDAeFw0xOTAxMDUxNzQxMzNaFw0xOTAyMDQxNzQxMzNaMBQx
EjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAMvnPNw1OBFmAjnmnKQkmV2Wb8yIC56f18Lf0ykEcx7KvuIzFS3YvOyXLQ4G
5lUySyw1uACZQ4R6IWa4rKlTEflvoMj7yKlkGhl5qKaPj/ZnsjRRi8BHWMX1p+e/
7Z/LNUa2CRBbHH8M9elNUIVke/vx0he22o6M2jRRwcqttClPLAlrY0BcdZXbSO+p
TwG9yrkt5+z8IDKeDM2VnwHwidsjn9+prkuQfPw4+wk84xUD7VR86YBjwpgtZGBq
0Ae3JqYtH59bkowd0vuktT5L6htMGC+F7uzwLRXBWQBSXI1MwmYvi16/Ts9eTIMU
RtAhNCnYeKLJB964II1eqwjiqisCAwEAAaNQME4wHQYDVR0OBBYEFHWdNYfHfiS8
NsoQLxtoIIIVhQSgMB8GA1UdIwQYMBaAFHWdNYfHfiS8NsoQLxtoIIIVhQSgMAwG
A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAIMtDzghpGxV7csdis+w39ER
yv6trB8bq9YfGsB1IhmPsg1AX+Hbf2niHiKoYXtqgKFTOv/QUS25ENHkLcJCL0Lk
RiGOg8aoMnkgj8vhNv9uQO5RbmcZP58fsCSLUdBPWQT3mLRU8JZ6z/xYBh37soI4
5wc9uTwHmeHoUF5Cl6KU7hZLJtmqUsc5Aj7x9IiY+Stqgb+V8f0D54zCDhS499Uf
mxVX6/3Aj0yMY6I6i5YQG3JpUbybdF96FvZDmiG+2KGGkD65U5iNzdoNbEs5wufC
W13nxOJi9oaC8XoHwKI3G6lAw2x8k34UPkIu/qdjiZfBtkoowsXuf9WN0UYLElo=
-----END CERTIFICATE-----

The code

The code for this tutorial will be very simple. The first thing we are going to do is importing the modules needed for the code to work. The first module we are going to need is the HTTP/2 module, which will make available the HTTP/2 related functionality.

const http2 = require('http2');

Additionally, we will need to import the file system module, so we can read both our certificate and private key files.

const fs = require('fs');

Next, we will need to define a callback function that will be executed when a HTTP/2 request is received by the server.

This function will be invoked with two arguments: an object of class Http2ServerRequest and an object of class Http2ServerResponse.

The first object may be used to access the request status, headers, and data [1]. Nonetheless, we are not going to use it for this tutorial.

The second object allows to send data back to the client and we are going to use it to send a “Hello World” message as response of the request.

function onRequest (req, resp) {
// implementation
}

Now, in order to send the response to the client, we will simply call the end method on our Http2ServerResponse object.

We will pass as input of this method a string with the content we want to send back to the client. Note that, besides sending the data back to the client, this method is responsible for signaling that all the content was sent and the message should be considered complete [1].

function onRequest (req, resp) {
	resp.end("Hello World");
}

After this, we can create our server by calling the createSecureServer function of the HTTP/2 module. As first input, this function receives a JavaScript object representing some options and, as second input, it can optionally receive a callback function to handle a request received event.

Regarding the first parameter, for this simple tutorial, we will have to create an object with two attributes called key and cert. The first attribute value should correspond to the private key we have previously generated and the second attribute should correspond to the server certificate we also generated.

We can read both files by calling the readFileSync function of the file system module, passing as input the path to the file. Note that, in the code below, I’m assuming that both the .pem files and the JavaScript file are located in the same directory, which is why I’m simply passing the file names and not the whole paths.

Regarding the second parameter, we simply need to pass the onRequest callback function we have defined earlier.

This function will return a Http2SecureServer instance, which we will store on a variable.

const server = http2.createSecureServer({
  key: fs.readFileSync('localhost-privkey.pem'),
  cert: fs.readFileSync('localhost-cert.pem')
}, onRequest);

Finally, we will call the listen method on the server object, passing as input the number of the port where it should listen to incoming requests. We will be using port 8443.

server.listen(8443);

The final code can be seen below.

const http2 = require('http2');
const fs = require('fs');

function onRequest (req, resp) {
	resp.end("Hello World");
}

const server = http2.createSecureServer({
  key: fs.readFileSync('localhost-privkey.pem'),
  cert: fs.readFileSync('localhost-cert.pem')
}, onRequest);

server.listen(8443);

Testing the code

To test the code, simply run the previous script on a tool of your choice. I’ll be using Visual Studio Code with the Code Runner extension.

After running the code, open a web browser of your choice with HTTP/2 support. I’m using Google Chrome. Then, access the following URL:

https://localhost:8443/stream

Note that the “/stream” path is optional and we can use another one if we want, since we are not defining which routes are valid in our server. In other words, it means that our server will always answer no matter which route we try to access.

Since we are using a self signed certificate, the browser should complain about security issues. Simply choose to advance.

You should get an output similar to figure 2, which shows the message we defined on the code.

Hello World response from node.js HTTP/2 server

Figure 2 – Response sent back to the client.

References

[1] https://nodejs.org/api/http2.html

[2] https://http2.github.io/faq/#does-http2-require-encryption

4 Replies to “Node.js: HTTP/2 server setup”

Leave a Reply