Send HTTP Requests To a Server with Node.js

It’s actually incredibly easy to send http/https requests to servers with Node.js. Node contains a bunch of native function for that, making it very easy to send REST requests. I’m going to demonstrate with Node’s own http.request(options[, callback]) method.

http-between-servers

HTTP/HTTPS requests in a very brief glance

The four most common HTTP requests are GET, POST, PUT, DELETE. The type of request determines the type of operation the request sender would like the server to perform.

If you’re sending REST API requests to a server, the documentation will(should) point you to exactly what the request is and how a sample request looks like.

GET is just the URL with or without headers. There are some common headers, like authorization. Without the headers it’s just like typing an address in your server. A GET request doesn’t change anything on the requested server.

An example GET request looks like this:

GET /viewingservice/v1/supported HTTP/1.1
Host: developer.api.autodesk.com
Authorization: Bearer OM0GTVs3ycQ0nkU9X9cneBnInOuE

POST is a request with headers and/or data. Data can usually be a string or a data stream, which means it’s a file.

An example POST request looks like this:

POST /authentication/v1/authenticate HTTP/1.1
Host: developer.api.autodesk.com
Content-Type: application/x-www-form-urlencoded
client_id=my_client_id&client_secret=my_client_secret&grant_type=client_credentials

PUT is similar to POST but idempotent, which means no matter how many times you send the request the result will be the same.

An example PUT request looks like this:

PUT /oss/v1/buckets/shiyas-bucket-100/objects/sometext.txt HTTP/1.1
Host: developer.api.autodesk.com
Authorization: Bearer OM0GTVs3ycQ0nkU9X9cneBnInOuE
Content-Type: application/octet-stream
"some text string"

Notice how the URI on the first line points to the exact location of the resource. No matter how many times I send the request, I will only have one resource that contains "some text string" with the URI /oss/v1/buckets/shiyas-bucket-100/objects/sometext.txt.

DELETE is what it sounds like, deleting a resource from the requested server. You need to know the exact URL of the resource you’d like to delete.

An example DELETE request looks like this:

DELETE /derivativeservice/v2/registration/{{resource_urn}} HTTP/1.1
Host: developer.api.autodesk.com
Authorization: Bearer glKJvrua6pWF5ogsOg9f3oOs69SC

It really is up to the discretion of who designs the API exactly what these request will do on their server.

Now we’ve understood what the requests do, it’s time to implement in Node.js.

http.request(options[, callback])

Node’s https is just http over TLS/SSL, the syntax are the same. When writing a https request, just replace http with https.

First include the http module:

var http = require("http");

Then create a variable called options, this is going to contain all the parameters in the request.

A POST request example:

var options = {
	host: "developer.api.autodesk.com",
	path: "/oss/v1/buckets",
	method: "POST",
	headers: {
		"Content-Type": "application/json"
		"Authorization": "Bearer token"
	}
};

A PUT request example:

var bucket = {};
bucket.name = "shiyas-bucket";

var file = {};
file.name = "sometext.txt";

var options = {
	host: "developer.api.autodesk.com",
	path: "/oss/v1/buckets/" + bucket.name + "/objects/" + file.name,
	method: "PUT", 
	headers: {
		"Content-Type": "application/octet-stream",
		"Authorization": "Bearer token"
	}
};

Notice how the path in the POST request is a general path while PUT request points to the exact location of the resource.

Now construct the request with options and a callback function.

The callback function occurs after you’ve sent the request, so it does things to the response, when you get one. In the callback function, write listeners that defines what you’d like to do when you get a response.

var req = http.request(options, function (res) {
	var responseString = "";

	res.on("data", function (data) {
		responseString += data;
		// save all the data from response
	});
	res.on("end", function () {
		console.log(responseString); 
		// print to console when response ends
	});
});

Sending the request:

req.write();

If there’s a request body, like in a POST or PUT request, pass in the request body.

var reqBody = "sometext";
req.write(reqBody);

reqBody here is a string, it can also be a buffer. Use a module like fs to handle file streams.

Lastly, end the request:

req.end();

That’s it!

Read Node’s documentation on http.request for more details.

Refer to one of my examples for complete working code.

10 thoughts on “Send HTTP Requests To a Server with Node.js”

  1. Shiya,
    That is a great example and well explained. I was wondering if you have used the above code for multiple calls (post) using a JSON file? The JSON file contains multiple records to be inserted. I kind of new to node JS and API.

    Thank you in advance

    J

    1. Hi J, what do you mean by multiple records?
      To send multiple requests, just make those calls with different parameters and wait for the response using callbacks. JSON is a JavaScript object, it can be parsed easily and you can spec out your API call according to the documentation of what you’re calling.

      1. Hi Shiya,

        Thank you for your reply.

        As I mentioned before, I am new to node js and API. The issue that I have is as such:
        I have a JSON file containing several records to be inserted, I would like to use node js and API to load them. I used your sample to load a single record from a JSON file and it works great. My issue is that, I do not know how to read the JSON file and perform a POST for each one of the records in the file.

        Thank you for any help you can give me.

        J

        1. Hey J,

          Do you have the JSON file? Or is it served on a server? And you’re fetching it and sending it back out?

          JSON string can be parsed using JSON.parse() method in JavaScript into an object. After that It works as a key-value pair. If you convert it into an object using let records = JSON.parse(retrievedJSON)


          {
          "albumName": "Some album"
          }

          You can access and edit it using records.albumName = 'New Album Name'

          Does this help? Let me know if I didn’t understand your question clearly.

          1. Hi Shiya,

            Thank you again for your replies.

            The JSON file is in a server, containing several records to be loaded into another server.

            I tried the JSON.parse, however, maybe I do not know how to send the records to the post request. I am ttaching my code so you can see it, maybe you can see what I am doing wrong.

            var async = require(‘async’);
            var http = require(‘http’);
            var fs = require(‘fs’);

            var post_data = JSON.parse(fs.readFileSync(‘S_CA_STU_ELA_C_insert_payload1.JSON’, ‘utf8’));

            async.each(post_data, function(data, callback){

            var post_options = {
            hostname: ‘https://devpshs.monet.k12.ca.us’,
            path : ‘/ws/schema/table/S_CA_STU_ELA_C’,
            method : ‘POST’,
            headers : {
            ‘Content-Type’: ‘application/json’,
            ‘Authorization’: ‘Bearer xxxxxxxxxxxxxxxxxxxxxxxxxx’
            }
            };

            post_req = http.request(post_options, function (res) {
            console.log(‘STATUS: ‘ + res.statusCode);
            console.log(‘HEADERS: ‘ + JSON.stringify(res.headers));
            res.setEncoding(‘utf8’);
            res.on(‘data’, function (chunk) {
            console.log(‘Response: ‘, chunk);
            });
            res.on(‘end’, function () {
            callback();
            });
            });

            post_req.on(‘error’, function(e) {
            console.log(‘problem with request: ‘ + e.message);
            });
            post_req.write(data);
            post_req.end();
            }, function(err){
            console.log(‘All requests done!’)
            });

            A sample of my JOSN file is:
            [
            {
            “studentsdcid”: “139007”,
            “ELAStatus”:”EO”,
            “ELAStatusStartDate”:”2011-03-01″,
            “ELAStatusEndDate”:””,
            “ExcludeFromStateReporting”:”0″,
            “PrimaryLanguage”:”00″

            },

            {
            “studentsdcid”: “132672”,
            “ELAStatus”:”EO”,
            “ELAStatusStartDate”:”2013-08-05″,
            “ELAStatusEndDate”:””,
            “ExcludeFromStateReporting”:”0″,
            “PrimaryLanguage”:””

            },

            {
            “studentsdcid”: “132672”,
            “ELAStatus”:”EO”,
            “ELAStatusStartDate”:”2013-08-05″,
            “ELAStatusEndDate”:””,
            “ExcludeFromStateReporting”:”0″,
            “PrimaryLanguage”:””
            }
            ]

            As I mentioned before, I can insert one record, so my thinking is that I could use the async.each to read each record, I tried it with out the async just parsing the file, the current code gives me the following error:
            TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be one of type string or Buffer

            I tried to change the var post_data to a buffer with no success.

            Thank you so much for taking the time to read questions and help me with this issue

            J

          2. Hi J, the code made it clear! Thanks! When you sent the request, the body needs to be a string and not a JSON object. In the request, just stringify the object again like so: post_req.write(JSON.stringify(data)); Let me know if you have any more trouble.

  2. Hi Shiya,

    I’ve created a custom nodejs server/ html page to get feedback from various clients.

    I was hoping that you can give me advice using POST requests…..

    At the moment I have,

    HTML
    function injectTrigger(controller, trigger){
    console.log(“Trigger ” + trigger + ” sending to ” + controller );
    $.ajax({
    type:”POST”,
    url:”/api/trigger/” + controller + “/” + trigger,
    async:true,
    timeout:1000,
    success: function(data){
    console.dir(data);
    }
    });

    Server (js)
    var static = require(‘node-static’);
    var url = require(“url”);
    var fs = require(‘fs’);
    var querystring = require(“querystring”);
    var http = require(‘http’);
    var WebSocketServer = require(‘ws’).Server
    const WSSPORT = 8080
    var subnet = “10.42.106.”; // Change for subnet

    var fileServer = new static.Server(‘./public’, { cache: 600 });
    //var fileServer = new static.Server(‘./_public/others’, { cache: 600 });
    require(‘http’).createServer(function (request,response) {
    var theUrl = url.parse(request.url);

    if (request.method == “GET” && theUrl.pathname.indexOf(“errors”) <0 && theUrl.pathname.indexOf("triggers") =0){
    //console.log(timeStamp() + ” Trigger ” + input [3] + ” received”);
    var input = theUrl.path.split(“/”);
    var controller = input [3];
    var trigger = input [3];
    injectTrigger(controller, data);
    }

    function injectTrigger(controller, trigger){

    var options = {
    host: subnet + controller,
    path: “api/trigger/” + trigger,
    port: “80”,
    headers: {
    “Content-Type”: “application/json”,
    “Authorization”: “No Auth”,
    }
    };
    console.log(options.host);
    console.log(options.path);
    var req = http.get(options, function(resp) {
    console.log(“trigger fired”);
    });
    req.on(‘error’, function(err) {

    req.end();
    }

    As it is it will not work because I need to use JSON raw data, but I am not sure how to do this?
    POST /api/trigger
    {
    “num”: num[,
    “var”: var…][,
    “conditions”: test_conditions]
    }

    Any advice would be appreciated.

    Thanks,

    1. Hi Hendrik,

      It’s hard to see from the code in text like this, posting a gist would be better.

      What are you trying to do with this piece of code? Are you trying to parse the request? When building an actual site I’d suggest using a library like Express and add something like body-parser to parse the JSON body of a request.

Leave a Reply

Your email address will not be published. Required fields are marked *

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