Native packages are one of the most performance oriented way to perform any task. While working with NodeJS one would encounter the most common task of making an HTTP request. There are multiple built-in packages and also third-party packages which can be used to do the same.

Out of all the above approaches only https comes out of the box in NodeJS without any additional installation. This also removes the additional overhead of bloating your code.

But then why do people use other packages? The reason is simple, the ease of implementation outweighs all the other benefits. But there would be cases where performance might be the deciding factor along with the bundle size, that's when people stumble upon the native https package for implementation, same was the case for me. Recently I had to implement HTTP call on Lambda@Edge function in Cloudfront, which shouldn't have any additional overhead of bundling , that's when I realized how different it was to work with the native package

Here is a working example of how you can make HTTP post request using native https in NodeJS.

const https = require('https');
function makeHttpPostRequest() {
    const options = {
        protocol: 'https:',
        hostname: 'postman-echo.com',
        port: 443,
        method: 'POST',
        path: '/post',
        headers: {
            'Content-Type': 'application/json',
            Authorization: 'Basic TOKEN'
        }
    };
    const postBody = {
        "req": "Post body"
    }
    return new Promise((resolve, reject) => {
        const req = https.request(options, (res) => {
            let body = '';
            res.on('data', (chunk) => {
                body += chunk;
            });

            res.on('end', () => {
                console.log(body)
                if (res.statusCode / 2 === 100 ) {
                    console.log('success')
                    resolve('Success');
                }
                else {
                    console.log('failed')
                    resolve('Failure');
                }
            });
            res.on('error', () => {
                console.log('error');
                reject(Error('HTTP call failed'));
            });
        });
        // The below 2 lines are most important part of the whole snippet.
        req.write(JSON.stringify(postBody));
        req.end();
    })
}

makeHttpPostRequest()

Here is a summary/details of the above code snippet

  • https - ┬ánative https is built-in package that does not need any additional ┬áinstallation
  • options variable is using to pass the details of the request
{
    protocol: 'https:',
    hostname: 'postman-echo.com',
    port: 443,
    method: 'POST',
    path: '/post',
    headers: {
        'Content-Type': 'application/json',
        Authorization: 'Basic TOKEN'
    }
}

hostname is the domain, port would be 443 for https and 80 for http request. method would be POST or GET or PUT or anything depending upon your requirement. path would be the URL which you need to make the request for. headers takes an object with keys as the name of the headers.

  • postBody would be a JSON object which you typically pass to the request.
  • passing the postBody to the request is the trick, you should pass the data outside of the https.request scope.
  • Make sure to convert the object to string before passing it to the request object since you are working on the native layer and all the data transfer at the native layer is happening as String which then gets converted into the binary form.
  • Also, remember to close the request by using req.end().

I hope the above example helps make native HTTPS requests, you can use similar syntax for HTTP requests over unsecured connections. I am attaching a curl request below for reference on how the original request looks like to sane humans

curl --location --request POST 'https://postman-echo.com/post' \
--header 'Authorization: Basic Token' \
--header 'Content-Type: application/json' \
--data-raw '{
    "req": "Post body"
}'