Tuesday, January 17, 2017

Node.js Request Module Tutorial

This is the 6th part of the tutorial series called Node Hero - in these chapters, you can learn how to get started with Node.js and deliver software products using it.
In the following tutorial, you will learn the basics of HTTP, and how you can fetch resources from external sources using the Node.js request module.

What's HTTP?

HTTP stands for Hypertext Transfer Protocol. HTTP functions as a request–response protocol in the client–server computing model.

HTTP Status Codes

Before diving into the communication with other APIs, let's review the HTTP status codes we may encounter during the process. They describe the outcome of our requests and are essential for error handling.
  • 1xx - Informational
  • 2xx - Success: These status codes indicate that our request was received and processed correctly. The most common success codes are 200 OK, 201 Created and 204 No Content.
  • 3xx - Redirection: This group shows that the client had to do an additional action to complete the request. The most common redirection codes are 301 Moved Permanently, 304 Not Modified.
  • 4xx - Client Error: This class of status codes is used when the request sent by the client was faulty in some way. The server response usually contains the explanation of the error. The most common client error codes are 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 409 Conflict. ​
  • 5xx - Server Error: These codes are sent when the server failed to fulfill a valid request due to some error. The cause may be a bug in the code or some temporary or permanent incapability. The most common server error codes are 500 Internal Server Error, 503 Service Unavailable. ​ If you'd like to learn more about HTTP status codes, you can find a detailed explanation about them here. 

Sending Requests to External APIs

Connecting to external APIs is easy in Node. You can just require the core HTTP module and start sending requests.
Of course, there are much better ways to call an external endpoint. On NPM you can find multiple modules that can make this process easier for you. Fo​r example, the two most popular ones are the request and superagent modules.
Both of these modules have an error-first callback interface that can lead to some issues (I bet you've heard about Callback-Hell), but luckily we have access to the promise-wrapped versions.

Using the Node.js Request Module

Using the request-promise module is simple. After installing it from NPM, you just have to require it:
const request = require('request-promise')  
​ Sending a GET request is as simple as:
const options = {  
  method: 'GET',
  uri: 'https://risingstack.com'
}request(options)  
  .then(function (response) {
    // Request was successful, use the response object at will
  })
  .catch(function (err) {
    // Something bad happened, handle the error
  })
If you are calling a JSON API, you may want the request-promise to parse the response automatically. In this case, just add this to the request options:
json: true  
​ POST requests work in a similar way:
const options = {  
  method: 'POST',
  uri: 'https://risingstack.com/login',
  body: {
    foo: 'bar'
  },
  json: true 
    // JSON stringifies the body automatically
}request(options)  
  .then(function (response) {
    // Handle the response
  })
  .catch(function (err) {
    // Deal with the error
  })
​ To add query string parameters you just have to add the qsproperty to the options object:
const options = {  
  method: 'GET',
  uri: 'https://risingstack.com',
  qs: {
    limit: 10,
    skip: 20,
    sort: 'asc'
  }
}
This will make your request URL: https://risingstack.com?limit=10&skip=20&sort=asc. 
​ You can also define any header the same way we added the query parameters:
const options = {  
  method: 'GET',
  uri: 'https://risingstack.com',
  headers: {
    'User-Agent': 'Request-Promise',
    'Authorization': 'Basic QWxhZGRpbjpPcGVuU2VzYW1l'
  }
}

Error handling

Error handling is an essential part of making requests to external APIs, as we can never be sure what will happen to them. Apart from our client errors the server may respond with an error or just send data in a wrong or inconsistent format. Keep these in mind when you try handling the response. Also, using catch for every request is a good way to avoid the external service crashing our server.

Putting it together

As you have already learned how to spin up a Node.js HTTP server, how to render HTML pages, and how to get data from external APIs, it is time to put them together!
In this example, we are going to create a small Express application that can render the current weather conditions based on​ city names.
(To get your AccuWeather​ API key, please visit their developer site)
const express = require('express')  
const rp = require('request-promise')  
const exphbs = require('express-handlebars')

const app = express()

app.engine('.hbs', exphbs({  
  defaultLayout: 'main',
  extname: '.hbs',
  layoutsDir: path.join(__dirname, 'views/layouts')
}))
app.set('view engine', '.hbs')  
app.set('views', path.join(__dirname, 'views'))

app.get('/:city', (req, res) => {  
  rp({
    uri: 'http://apidev.accuweather.com/locations/v1/search',
    qs: {
      q: req.params.city,
      apiKey: 'api-key'
         // Use your accuweather API key here
    },
    json: true
  })
    .then((data) => {
      res.render('index', data)
    })
    .catch((err) => {
      console.log(err)
      res.render('error')
    })
})

app.listen(3000)  
The example above does the following:
  • creates an Express server
  • sets up the handlebars structure - for the .hbs file please refer to the Node.js HTTP tutorial
  • sends a request to the external API
    • if everything is ok, it renders the page
    • otherwise, it shows the error page and logs the error

No comments:

Post a Comment