Node.js

Node.js HTTP Request Example

In this post we take a look at how to make HTTP Requests with Node.js. This feature is key and important capability for a server side language. With Node.js being positioned as one of the best options for aggregating multiple services and high throughput due to its non blocking I/O operations, it is an important feature to learn about. So let us build an example where we make exactly this in Node.js.

1. Tools & Technologies

I have used the following toolset & technologies to build the example application. The tools may be switched out with others you are more comfortable with.

  1. Node.js v6.3.0
  2. HTTP Module
  3. request Module v2.83.0
  4. json-server v0.12.1
  5. Visual Studio Code IDE


 
Node.js is a JavaScript framework for running JavaScript on the server side. HTTP module, part of Node.js, allows us to handle requests from browser and issue HTTP Requests of our own to services. We will use the json-server module to mock a service API. I will go through, in a later section, with the details of setting all of this up. I have used the Visual Studio Code IDE as I feel most comfortable with it, though you are free to switch to one of many available IDEs out there.

2. Project Layout

The structure of our project would look like below:

Project Layout

You can easily initialize and prepare an initial project structure using the commands below at the root of the folder you want it to reside in.

> npm init

This command asks a few basic questions and suggests defaults for them as well. Apart from a few you can go along with the suggestions to setup initial project structure.
You can create the css, js folders and the files in them manually using command line or GUI or from within the IDE. The two modules that our example depends on and their dependencies can be installed and saved using the following commands:

> npm install --save request

followed by

> npm install --save json-server

3. Server Side Implementation with Http & json-server Modules

We use Http to create a web server of our own. This server would listen to service requests from the browser and relaying them on to our own mock service. Apart from this it will also handle requests for resource files like JavaScript, css and Html files.

3.1 Http Module

The http module is part of Node.js and gives us the capability to create a basic web server. We include this module through a require statement and then call its createServer method. This method takes a callback to which it passes the response and request object for the incoming requests. We also specify the hostname and port to listen for requests on.
We use the url module, part of Node.js, to handle incoming requests and return appropriate responses for each. The code for this resides in the file index.js at the root of our project. Our index.js file with the web server code looks like below:

index.js

//including Node.js modules
var http = require("http");
var url = require("url");
var fs = require("fs");

//Url of our web server
var host = "localhost";
var port = 8090;

//Setting up our web server
http.createServer(function(req, res){
    var path = url.parse(req.url, true);
    if(path.pathname.endsWith("html")){
        fs.readFile("." + path.pathname, function(err, data){
            res.writeHead(200, "OK", { "Content-Type": "text/html"} );
            res.write(data);
            res.end();
        });
    } else if(path.pathname.endsWith("css")){
        fs.readFile("." + path.pathname, function(err, data){
            res.writeHead(200, "OK", { "Content-Type": "text/css"});
            res.write(data);
            res.end();
        });
    } else if(path.pathname.endsWith("js")){
        fs.readFile("." + path.pathname, function(err, data){
            res.writeHead(200, "OK", { "Content-Type": "text/javascript"});
            res.write(data);
            res.end();
        });

    } else if(path.pathname.endsWith("names")){
        switch(req.method){
            case "GET": api.getRequest(res, path.query.team);            
            break;
            case "POST": 
            var data = "";
            req.on("data", function(d){
                data+=d;
            });
            req.on("end", function(){
                api.postRequest(data, res);
            });            
            break;            
            case "DELETE":
            var delData = "";
            req.on("data", function(d){
                delData += d;
            });
            req.on("end", function(){
                api.deleteRequest(res, delData);
            });
            break;
        }
    }
}).listen(port, host);

In the Next section, we setup our mock service using the json-server module.

3.2 json-server Module

This module allows us to quickly mock a service API. The API is backed with a store of some test data in a file called db.json. Our data store is in the folder called db and its contents look as follows:

db.json

{
  "myTeam": [
    {
      "id": 1,
      "name": "Mahendra Singh Dhoni"
    },
    {
      "id": 2,
      "name": "Virat Kohli"
    },
    {
      "id": 3,
      "name": "Bhuvneshvar Kumar"
    },
    {
      "id": 4,
      "name": "Mohmd. Shami"
    },
    {
      "id": 5,
      "name": "Ishant Sharma"
    },
    {
      "id": 6,
      "name": "Ajinkya Rahane"
    },
    {
      "id": 7,
      "name": "K L Rahul"
    },
    {
      "id": 8,
      "name": "Yuvraj Singh"
    },
    {
      "id": 9,
      "name": "Harbhajan Singh"
    },
    {
      "id": 10,
      "name": "Kuldeep Yadav"
    },
    {
      "id": 11,
      "name": "Yajuvendra Chahal"
    }
  ],
  "yourTeam": [
    
  ]
}

As evident from the data we will build a page showing my dream cricket team whilst allowing users to create one of their own with their favorite players.
The code to setup this mock service resides in the index.js file and it looks like below:

index.js

var jsonServer = require('json-server');
var server = jsonServer.create();
var router = jsonServer.router('./db/db.json');
var middlewares = jsonServer.defaults();

server.use(middlewares);
server.use(router);

server.listen(9090, function() {
  console.log('JSON Server is running');
});

As you can notice from the snippet the mock service runs on the URL http://localhost:9090.
Now finally we create a file named http.request.server.js to organize the code for making service calls to our mock service. We later include it into our index.js file through a require statement. In this file we have methods to enable requests using different HTTP verbs like GET, POST, DELETE among others. The http.request.server.js file looks like below:

http.request.server.js

var request = require("request");
var host = "http://127.0.0.1";
var port = 9090;
var api ={
    getRequest:function(res, team){
        if(team){
            request.get(host + ":" + port + "/yourTeam", function(error, response, body){
                res.writeHead(200, "OK", { "Content-Type":"application/json", "Access-Control-Allow-Origin" : "http://localhost:8090"});
                res.write(body);
                res.end();
            });
        }
        else{
            request.get(host + ":" +port + "/myTeam", function(error, response, body){
                res.writeHead(200, "OK", { "Content-Type":"application/json", "Access-Control-Allow-Origin" : "http://localhost:8090"});
                res.write(body);
                res.end();
            });
        }
    },
    postRequest: function (player, res){
        request.post(host + ":" + port +"/yourTeam", function(error, response, body){
            res.writeHead(200, "OK");
            res.write(body);
            res.end();
        }).form(JSON.parse(player));
    },
    deleteRequest: function (res, id){
        var player = JSON.parse(id);
        request.del(host + ":" + port + "/yourTeam/" + player.playerId, function(error, response, body){
            res.writeHead(200, "OK");
            res.write(body);
            res.end();
        });
    }
};
module.exports = api;

We use the request module to make calls to the mock service. As you can see from the code above we have a method for each one of the HTTP verbs we will use in our example, although all HTTP verbs are supported by this mock service. We will stick to GET, POST, DELETE to keep things simple in our example.

4. Client Side Implementation with JavaScript, HTML & CSS

Onwards now to build our front end and make calls to the server as a result of user actions. We start off with a standard HTML and adding markup to display two teams as ordered lists. We also add html to allow the user to add players to their own team. Each team member added by the user would also have a link to remove the player from the list. We achieve the hover effect and styling by adding css in the http.request.css file. Our final Html markup looks like below:

index.html

  
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
<title>WCG -- Node.js HTTP Request Example</title>

<link rel="Stylesheet" href="css/http.request.css"/>
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://www.webcodegeeks.com/wp-content/litespeed/localres/aHR0cHM6Ly9vc3MubWF4Y2RuLmNvbS8=html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://www.webcodegeeks.com/wp-content/litespeed/localres/aHR0cHM6Ly9vc3MubWF4Y2RuLmNvbS8=respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<h1>WCG -- Node.js HTTP Request Example</h1>
<div class="teams">
<div class="myteam">
My All Star Cricket 11
</div>
<div class="yourteam">
Yours?
</div>
<div class="addplayers">
<input type="text" placeholder="Player Name" id="playerName"/>
<input type="button" value="Add" id="addPlayer" />
</div>
</div>
<script src="js/http.request.js"></script>
</body>
</html>

4.1 Ajax calls with JavaScript

We use the XMLHttpRequest object to issue calls to the server which in turn makes calls to our mock service. The code for the client side resides in http.request.js file. We load both teams at startup. Apart from this we make a call to add team players in user’s team on the click of the Add button. Similarly we make a call when the delete player link is clicked. After each call we also make request for the updated team. Our client side code now looks as follows:

http.request.js

var myteam = document.getElementsByClassName("myteam")[0];
var addPlayer = document.getElementById("addPlayer");
var playerName = document.getElementById("playerName");
var deleteLink = document.getElementsByClassName("deletelink");
var yourteam = document.getElementsByClassName("yourteam")[0];
var host = "http://localhost";
var port = "8090";

function setupDeleteLink(){
    for(var l=0; l<deleteLink.length; l++){
        deleteLink[l].addEventListener("click", function(event){
            var xmlHttp = new XMLHttpRequest();
            var ctrl = event.target;
            xmlHttp.onreadystatechange = function(){
                if(xmlHttp.status === 200 && xmlHttp.readyState === 4){
                    console.log(xmlHttp.responseText);
                    refreshYourTeam();
                }
            };
            xmlHttp.open("DELETE",  host +":" + port + "/names");
            xmlHttp.send(JSON.stringify({ "playerId": ctrl.getAttribute("playerId")}));
        });
    }
}

addPlayer.addEventListener("click", function(){
    var player = {};
    player.name = playerName.value;
    var xmlHttp = new XMLHttpRequest();
    xmlHttp.onreadystatechange = function(){

        if(xmlHttp.status === 200 && xmlHttp.readyState === 4){
            console.log(xmlHttp.responseText);
            refreshYourTeam();
        }
    
    };
    xmlHttp.open("POST", host +":" + port + "/names");
    xmlHttp.send(JSON.stringify(player));
    
});

function Initialize(){
    var xmlHttp = new XMLHttpRequest();
    xmlHttp.onreadystatechange = function(){

        if(xmlHttp.status === 200 && xmlHttp.readyState === 4){
            console.log(xmlHttp.responseText);
            populateMyTeam(xmlHttp.responseText);
        }
    
    };
    xmlHttp.open("GET", host + ":" + port + "/names", true);    
    xmlHttp.withCredentials = false;
    xmlHttp.send();
}

function refreshYourTeam(){
    var xmlHttp = new XMLHttpRequest();
    xmlHttp.onreadystatechange = function(){

        if(xmlHttp.status === 200 && xmlHttp.readyState === 4){
            console.log(xmlHttp.responseText);
            populateYourTeam(xmlHttp.responseText);
        }
    
    };
    xmlHttp.open("GET", host + ":" + port + "/names?team=yourTeam", true);
    xmlHttp.send();
}
function populateYourTeam(team){
    var orderedList = document.createElement("OL");
    var players = JSON.parse(team);

    for(var i=0; i < players.length; i++){
        var listItem = document.createElement("LI");
        var delLink = document.createElement("SPAN");
        delLink.className = "deletelink";
        delLink.appendChild(document.createTextNode("X"));
        delLink.setAttribute("playerId", players[i].id);
        listItem.appendChild(document.createTextNode(players[i].name));
        listItem.appendChild(delLink);
        orderedList.appendChild(listItem);
        
    }
    yourteam.innerHTML = orderedList.outerHTML;

    setupDeleteLink();
}
function populateMyTeam(team){
    var orderedList = document.createElement("OL");
    var players = JSON.parse(team);

    for(var i=0; i < players.length; i++){
        var listItem = document.createElement("LI");
        
        listItem.appendChild(document.createTextNode(players[i].name));
       
        orderedList.appendChild(listItem);
        
    }
    myteam.appendChild(orderedList);

}
Initialize();
refreshYourTeam();

5. Running the Application

To run the application you need to navigate to the root of the application and run the following command:

> node index.js

Once the command completes you can navigate to the URL http://localhost:8090/index.html in a browser.
This takes you to the landing page of our application which looks like below:

Landing Page – index.html

6. Download the Source Code

This wraps our look at making HTTP Requests with Node.js example.

Download
You can download the full source code of this example here : WCG — Node.js HTTP Request Example

Siddharth Seth

Siddharth is a Software Development Professional with a Master degree in Computer Applications from IGNOU. He has over 14 years of experience. And currently focused on Software Architecture, Cloud Computing, JavaScript Frameworks for Client and Server, Business Intelligence.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button