5 Ways to Make HTTP Requests in Node.js

August 09, 2017
Written by
Sam Agnew
Twilion

Making HTTP requests is a core functionality for modern languages and one of the first things many developers learn when acclimating to new environments. When it comes to Node.js there are a fair amount of solutions to this problem both built into the language and by the community. Let’s take a look at some of the most popular ones.

We’ll be using NASA’s Astronomy Picture of the Day API as the JSON API that we are interacting with in all of these examples because space is the coolest thing ever.

 

giphy.gif


Before moving on, make sure you have up to date versions of Node.js and npm installed on your machine.

HTTP - the Standard Library

First on our hit parade is the default HTTP module in the standard library. With this module, you can just plug and go without having to install external dependencies. The downside is that it isn’t very user friendly compared to other solutions.

The following code will send a GET request to NASA’s API and print out the URL for the astronomy picture of the day as well as an explanation:

 

const https = require('https');

https.get('https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY', (resp) => {
  let data = '';

  // A chunk of data has been received.
  resp.on('data', (chunk) => {
    data += chunk;
  });

  // The whole response has been received. Print out the result.
  resp.on('end', () => {
    console.log(JSON.parse(data).explanation);
  });

}).on("error", (err) => {
  console.log("Error: " + err.message);
});

Much of the HTTP, and the HTTPS, module’s functionality is fairly low-level. You’re required to receive response data in chunks rather than just providing a callback function to be executed as soon as all of the data is received. You also need to parse the response data manually. This is fairly trivial if it is JSON formatted, but it is still an extra step.

One other problem is that this module does not support HTTPS by default, so we need to require the https module instead if the API we are using communicates over HTTPS.
It may take a bit more effort to get the data you want, but is a great utility if you don’t want to add too many dependencies to your codebase or want access to its low level functionality.

node-fetch

node-fetch is a light weight module that brings the browser library window.fetch to Node.js with minimal code. Unlike the http module, you will have to install this one as a dependency from npm.

Run the following in your terminal from the directory you want your code to live in:

 

npm install node-fetch@2.6.0

Recent versions of this library use promises, so we're able to use async/await syntax with it as well:

const fetch = require('node-fetch');

(async () => {
  try {

    const response = await fetch('https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY')
    const json = await response.json()

    console.log(json.url);
    console.log(json.explanation);
  } catch (error) {
    console.log(error.response.body);
  }
})();

This library does have a built in function for converting the response to JSON, but it does not do it automatically in the same way that some of the following libraries do. This one is great for people who are used to using the Fetch API in the browser.

Axios

Axios is a Promise based HTTP client for the browser as well as node.js. Using Promises is a great advantage when dealing with code that requires a more complicated chain of events. Writing asynchronous code can get confusing, and Promises are one of several solutions to this problem. They are even useful in other languages such as Swift.

To install Axios from npm, enter the following command in your terminal:

 

npm install axios@0.21.1

The following code will accomplish the same task of logging the URL to and of explaining the astronomy picture of the day:

 

const axios = require('axios');

axios.get('https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY')
  .then(response => {
    console.log(response.data.url);
    console.log(response.data.explanation);
  })
  .catch(error => {
    console.log(error);
  });

Axios even parses JSON responses by default. Pretty convenient! You can also see that error handling is done with .catch() since we are using promises now.

You can even make multiple concurrent requests with axios.all if you wanted to do something like get the astronomy picture of two different days at once:

 

var axios = require('axios');

axios.all([
  axios.get('https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY&date=2017-08-03'),
  axios.get('https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY&date=2017-08-02')
]).then(axios.spread((response1, response2) => {
  console.log(response1.data.url);
  console.log(response2.data.url);
})).catch(error => {
  console.log(error);
});

Asynchronous code can easily become over complicated and unpleasant to deal with, and the way Axios tackles this problem may make your life easier in the long run.

SuperAgent

Similarly to Axios, SuperAgent is another popular library primarily used for making AJAX requests in the browser but works in Node.js as well. Install SuperAgent with the following command:

 

npm install superagent@6.1.0

What is cool about SuperAgent is that you have other useful functions that you can chain onto requests such as query() to add parameters to the request. We’ve been just manually adding them in the URL in the previous examples, but notice how SuperAgent gives you a function to do this:

 

const superagent = require('superagent');

superagent.get('https://api.nasa.gov/planetary/apod')
.query({ api_key: 'DEMO_KEY', date: '2017-08-02' })
.end((err, res) => {
  if (err) { return console.log(err); }
  console.log(res.body.url);
  console.log(res.body.explanation);
});

Just like with Axios you don’t have to parse the JSON response yourself, which is pretty cool.

Got

Got is another choice if you want a more lightweight library. It is also available to use in Twilio Functions.

Again, install Got with npm:

 

npm install got@7.1.0

Similarly to Axios, Got works with Promises as well. The following code will work as the rest of the examples do:

 

const got = require('got');

got('https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY', { json: true }).then(response => {
  console.log(response.body.url);
  console.log(response.body.explanation);
}).catch(error => {
  console.log(error.response.body);
});

Got is great if you want a smaller library that feels less “bloated” than something like Request.

Final thoughts

This doesn’t cover all of the solutions, but now you see how the basic functionality works in a few of the most popular HTTP libraries in Node. There are also libraries such as node-fetch which ports the browser’s fetch functionality to the backend.

Other languages have a similar variety of libraries to tackle this problem. Check out these other tutorials in SwiftPython and Ruby. Also, check out our Node.js Quickstarts for a place to apply your new skills.

What are your favorite ways to send HTTP requests? Feel free to reach out and let me know or ask any questions: