httprequest json - How to make an HTTP POST request in node.js?




handle https (15)

How can I make an outbound HTTP POST request, with data, in node.js?


Answers

You can use request library. https://www.npmjs.com/package/request

var request = require('request');

To post JSON data:

var myJSONObject = { ... };
request({
    url: "http://josiahchoi.com/myjson",
    method: "POST",
    json: true,   // <--Very important!!!
    body: myJSONObject
}, function (error, response, body){
    console.log(response);
});

To post xml data:

var myXMLText = '<xml>...........</xml>'
request({
    url: "http://josiahchoi.com/myjson",
    method: "POST",
    headers: {
        "content-type": "application/xml",  // <--Very important!!!
    },
    body: myXMLText
}, function (error, response, body){
    console.log(response);
});

var https = require('https');


/**
 * HOW TO Make an HTTP Call - POST
 */
// do a POST request
// create the JSON object
jsonObject = JSON.stringify({
    "message" : "The web of things is approaching, let do some tests to be ready!",
    "name" : "Test message posted with node.js",
    "caption" : "Some tests with node.js",
    "link" : "http://www.youscada.com",
    "description" : "this is a description",
    "picture" : "http://youscada.com/wp-content/uploads/2012/05/logo2.png",
    "actions" : [ {
        "name" : "youSCADA",
        "link" : "http://www.youscada.com"
    } ]
});

// prepare the header
var postheaders = {
    'Content-Type' : 'application/json',
    'Content-Length' : Buffer.byteLength(jsonObject, 'utf8')
};

// the post options
var optionspost = {
    host : 'graph.facebook.com',
    port : 443,
    path : '/youscada/feed?access_token=your_api_key',
    method : 'POST',
    headers : postheaders
};

console.info('Options prepared:');
console.info(optionspost);
console.info('Do the POST call');

// do the POST call
var reqPost = https.request(optionspost, function(res) {
    console.log("statusCode: ", res.statusCode);
    // uncomment it for header details
//  console.log("headers: ", res.headers);

    res.on('data', function(d) {
        console.info('POST result:\n');
        process.stdout.write(d);
        console.info('\n\nPOST completed');
    });
});

// write the json data
reqPost.write(jsonObject);
reqPost.end();
reqPost.on('error', function(e) {
    console.error(e);
});

For those coming here in the later years. There are now a wide variety of different libraries that can accomplish this with minimal coding. I much prefer elegant light weight libraries for HTTP requests unless you absolutely need control of the low level HTTP stuff.

One such library is Unirest

To install it, use npm.
$ npm install unirest

And onto the Hello, World! example that everyone is accustomed to.

var unirest = require('unirest');

unirest.post('http://example.com/helloworld')
.header('Accept', 'application/json')
.send({ "Hello": "World!" })
.end(function (response) {
  console.log(response.body);
});


Extra:
A lot of people are also suggesting the use of request [ 2 ]

It should be worth noting that behind the scenes Unirest uses the request library.

Unirest provides methods for accessing the request object directly.

Example:

var Request = unirest.get('http://mockbin.com/request');

Posting another axios example of an axios.post request that uses additional configuration options and custom headers.

var postData = {
  email: "[email protected]",
  password: "password"
};

let axiosConfig = {
  headers: {
      'Content-Type': 'application/json;charset=UTF-8',
      "Access-Control-Allow-Origin": "*",
  }
};

axios.post('http://<host>:<port>/<path>', postData, axiosConfig)
.then((res) => {
  console.log("RESPONSE RECEIVED: ", res);
})
.catch((err) => {
  console.log("AXIOS ERROR: ", err);
})


You can also use Requestify, a really cool and simple HTTP client I wrote for nodeJS + it supports caching.

Just do the following:

    var requestify = require('requestify');

    requestify.post('http://example.com', {
        hello: 'world'
    })
    .then(function(response) {
        // Get the response body (JSON parsed or jQuery object for XMLs)
        response.getBody();
    });

To Post Rest/JSON Request
We can simply use request package and save the values we have to send in Json variable.

First install the require package in your console by npm install request --save

var request = require('request');

    var options={
                'key':'28',
                'key1':'value',
                'key2':'value'
                }

    request({
             url:"http://dev.api.ean.com/ean-services/rs/hotel/v3/ping?                      
                 minorRev="+options.key+
                 "&cid="+options.key1+
                 "&apiKey="+options.key2,
             method:"POST",
             json:true},function(error,response,body){
                     console.log(body)
               }
    );

Here's an example of using node.js to make a POST request to the Google Compiler API:

// We need this to build our post string
var querystring = require('querystring');
var http = require('http');
var fs = require('fs');

function PostCode(codestring) {
  // Build the post string from an object
  var post_data = querystring.stringify({
      'compilation_level' : 'ADVANCED_OPTIMIZATIONS',
      'output_format': 'json',
      'output_info': 'compiled_code',
        'warning_level' : 'QUIET',
        'js_code' : codestring
  });

  // An object of options to indicate where to post to
  var post_options = {
      host: 'closure-compiler.appspot.com',
      port: '80',
      path: '/compile',
      method: 'POST',
      headers: {
          'Content-Type': 'application/x-www-form-urlencoded',
          'Content-Length': Buffer.byteLength(post_data)
      }
  };

  // Set up the request
  var post_req = http.request(post_options, function(res) {
      res.setEncoding('utf8');
      res.on('data', function (chunk) {
          console.log('Response: ' + chunk);
      });
  });

  // post the data
  post_req.write(post_data);
  post_req.end();

}

// This is an async file read
fs.readFile('LinkedList.js', 'utf-8', function (err, data) {
  if (err) {
    // If this were just a small part of the application, you would
    // want to handle this differently, maybe throwing an exception
    // for the caller to handle. Since the file is absolutely essential
    // to the program's functionality, we're going to exit with a fatal
    // error instead.
    console.log("FATAL An error occurred trying to read in the file: " + err);
    process.exit(-2);
  }
  // Make sure there's data before we post it
  if(data) {
    PostCode(data);
  }
  else {
    console.log("No data to post");
    process.exit(-1);
  }
});

I've updated the code to show how to post data from a file, instead of the hardcoded string. It uses the async fs.readFile command to achieve this, posting the actual code after a successful read. If there's an error, it is thrown, and if there's no data the process exits with a negative value to indicate failure.


After struggling a lot while creating a low level utility to handle the post and get requests for my project, I decided to post my effort here. Much on the lines of accepted answer, here is a snippet for making http and https POST requests for sending JSON data.

const http = require("http")
const https = require("https")

// Request handler function
let postJSON = (options, postData, callback) => {

    // Serializing JSON
    post_data = JSON.stringify(postData)

    let port = options.port == 443 ? https : http

    // Callback function for the request
    let req = port.request(options, (res) => {
        let output = ''
        res.setEncoding('utf8')

        // Listener to receive data
        res.on('data', (chunk) => {
            output += chunk
        });

        // Listener for intializing callback after receiving complete response
        res.on('end', () => {
            let obj = JSON.parse(output)
            callback(res.statusCode, obj)
        });
    });

   // Handle any errors occurred while making request
    req.on('error', (err) => {
        //res.send('error: ' + err.message)
    });

    // Request is made here, with data as string or buffer
    req.write(post_data)
    // Ending the request
    req.end()
};

let callPost = () => {

    let data = {
        'name': 'Jon',
        'message': 'hello, world'
    }

    let options = {
        host: 'domain.name',       // Your domain name
        port: 443,                 // 443 for https and 80 for http
        path: '/path/to/resource', // Path for the request
        method: 'POST',            
        headers: {
            'Content-Type': 'application/json',
            'Content-Length': Buffer.byteLength(data)
        }
    }

    postJSON(options, data, (statusCode, result) => {
        // Handle response
        // Process the received data
    });

}

Simple and dependency-free. Uses a Promise so that you can await the result. It returns the response body and does not check the response status code.

const https = require('https');

function httpsPost({body, ...options}) {
    return new Promise((resolve,reject) => {
        const req = https.request({
            method: 'POST',
            ...options,
        }, res => {
            const chunks = [];
            res.on('data', data => chunks.push(data))
            res.on('end', () => {
                let body = Buffer.concat(chunks);
                switch(res.headers['content-type']) {
                    case 'application/json':
                        body = JSON.parse(body);
                        break;
                }
                resolve(body)
            })
        })
        req.on('error',reject);
        if(body) {
            req.write(body);
        }
        req.end();
    })
}

Usage:

const res = await httpsPost({
    hostname: 'sentry.io',
    path: `/api/0/organizations/org/releases/${changesetId}/deploys/`,
    headers: {
        'Authorization': `Bearer ${process.env.SENTRY_AUTH_TOKEN}`,
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        environment: isLive ? 'production' : 'demo',
    })
})

If you are looking for promise based HTTP requests, axios does its job nicely.

  const axios = require('axios');

  axios.post('/user', {
    firstName: 'Fred',
    lastName: 'Flintstone'
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

This gets a lot easier if you use the request library.

var request = require('request');

request.post(
    'http://www.yoursite.com/formpage',
    { json: { key: 'value' } },
    function (error, response, body) {
        if (!error && response.statusCode == 200) {
            console.log(body)
        }
    }
);

Aside from providing a nice syntax it makes json requests easy, handles oauth signing (for twitter, etc.), can do multi-part forms (e.g. for uploading files) and streaming.

To install request use command npm install request


By using request dependency.

Simple solution :

 import request from 'request'
 var data = {
        "host":"127.1.1.1",
        "port":9008
    }

request.post( baseUrl + '/peers/connect',
        {
            json: data,  // your payload data placed here
            headers: {
                'X-Api-Key': 'dajzmj6gfuzmbfnhamsbuxivc', // if authentication needed
                'Content-Type': 'application/json' 
            }
        }, function (error, response, body) {
            if (error) {
                callback(error, null)
            } else {
                callback(error, response.body)
            }
        });

This my solution for POST and GET.

About the Post method:

If the body is a JSON object, so it's important to deserialize it with JSON.stringify and possibly set the Content-Lenght header accordingly:

      var bodyString=JSON.stringify(body)
      var _headers = {
        'Content-Length': Buffer.byteLength(bodyString)
      };

before writing it to the request:

request.write( bodyString );

About both Get and Post methods:

The timeout can occur as a socket disconnect, so you must register its handler like:

request.on('socket', function (socket) {
        socket.setTimeout( self.timeout );
        socket.on('timeout', function() {
            request.abort();
            if(timeout) return timeout( new Error('request timed out') );
        });
    });

while the request handler is

       request.on('timeout', function () {
          // Timeout happend. Server received request, but not handled it
          // (i.e. doesn't send any response or it took to long).
          // You don't know what happend.
          // It will emit 'error' message as well (with ECONNRESET code).
          req.abort();
          if(timeout) return timeout( new Error('request timed out') );
        });

I strongly suggest to register both the handlers.

The response body is chunked, so you must concat chunks at the data handler:

      var body = '';
      response.on('data', function(d) {
          body += d;
      });

At the end the body will contain the whole response body:

      response.on('end', function() {
        try {
            var jsonResponse=JSON.parse(body);
            if(success) return success( jsonResponse );
        } catch(ex) { // bad json
          if(error) return error(ex.toString());
        }
      });

It is safe to wrap with a try...catchtheJSON.parse` since you cannot be sure that it is a well-formatted json actually and there is no way to be sure of it at the time you do the request.

Module: SimpleAPI

/**
 * Simple POST and GET
 * @author Loreto Parisi (loretoparisi at gmail dot com)
*/
(function() {

  var SimpleAPI;

  SimpleAPI = (function() {

    var qs = require('querystring');

    /**
     * API Object model
     * @author Loreto Parisi (loretoparisi at gmail dot com)
     */
    function SimpleAPI(host,port,timeout,ssl,debug,json) {

      this.host=host;
      this.port=port;
      this.timeout=timeout;
      /** true to use ssl - defaults to true */
      this.ssl=ssl || true;
      /** true to console log */
      this.debug=debug;
      /** true to parse response as json - defaults to true */
      this.json= (typeof(json)!='undefined')?json:true;
      this.requestUrl='';
      if(ssl) { // use ssl
          this.http = require('https');
      } else { // go unsafe, debug only please
          this.http = require('http');
      }
    }

    /**
     * HTTP GET
     * @author Loreto Parisi (loretoparisi at gmail dot com)
     */
    SimpleAPI.prototype.Get = function(path, headers, params, success, error, timeout) {

      var self=this;
      if(params) {
        var queryString=qs.stringify(params);
        if( queryString ) {
          path+="?"+queryString;
        }
      }
      var options = {
        headers : headers,
        hostname: this.host,
        path: path,
        method: 'GET'
      };
      if(this.port && this.port!='80') { // port only if ! 80
        options['port']=this.port;
      }
      if(self.debug) {
        console.log( "SimpleAPI.Get", headers, params, options );
      }
      var request=this.http.get(options, function(response) {

          if(self.debug) { // debug
            console.log( JSON.stringify(response.headers) );
          }

          // Continuously update stream with data
          var body = '';
          response.on('data', function(d) {
              body += d;
          });
          response.on('end', function() {
            try {
              if(self.json) {
                var jsonResponse=JSON.parse(body);
                if(success) return success( jsonResponse );
              }
              else {
                if(success) return success( body );
              }
            } catch(ex) { // bad json
              if(error) return error( ex.toString() );
            }
          });
        });
        request.on('socket', function (socket) {
            socket.setTimeout( self.timeout );
            socket.on('timeout', function() {
                request.abort();
                if(timeout) return timeout( new Error('request timed out') );
            });
        });
        request.on('error', function (e) {
          // General error, i.e.
          //  - ECONNRESET - server closed the socket unexpectedly
          //  - ECONNREFUSED - server did not listen
          //  - HPE_INVALID_VERSION
          //  - HPE_INVALID_STATUS
          //  - ... (other HPE_* codes) - server returned garbage
          console.log(e);
          if(error) return error(e);
        });
        request.on('timeout', function () {
          // Timeout happend. Server received request, but not handled it
          // (i.e. doesn't send any response or it took to long).
          // You don't know what happend.
          // It will emit 'error' message as well (with ECONNRESET code).
          req.abort();
          if(timeout) return timeout( new Error('request timed out') );
        });

        self.requestUrl = (this.ssl?'https':'http') + '://' + request._headers['host'] + request.path;
        if(self.debug) {
          console.log("SimpleAPI.Post",self.requestUrl);
        }
        request.end();
    } //RequestGet

    /**
     * HTTP POST
     * @author Loreto Parisi (loretoparisi at gmail dot com)
     */
    SimpleAPI.prototype.Post = function(path, headers, params, body, success, error, timeout) {
      var self=this;

      if(params) {
        var queryString=qs.stringify(params);
        if( queryString ) {
          path+="?"+queryString;
        }
      }
      var bodyString=JSON.stringify(body)
      var _headers = {
        'Content-Length': Buffer.byteLength(bodyString)
      };
      for (var attrname in headers) { _headers[attrname] = headers[attrname]; }

      var options = {
        headers : _headers,
        hostname: this.host,
        path: path,
        method: 'POST',
        qs : qs.stringify(params)
      };
      if(this.port && this.port!='80') { // port only if ! 80
        options['port']=this.port;
      }
      if(self.debug) {
        console.log( "SimpleAPI.Post\n%s\n%s", JSON.stringify(_headers,null,2), JSON.stringify(options,null,2) );
      }
      if(self.debug) {
        console.log("SimpleAPI.Post body\n%s", JSON.stringify(body,null,2) );
      }
      var request=this.http.request(options, function(response) {

          if(self.debug) { // debug
            console.log( JSON.stringify(response.headers) );
          }

          // Continuously update stream with data
          var body = '';
          response.on('data', function(d) {
              body += d;
          });
          response.on('end', function() {
            try {
                console.log("END", body);
                var jsonResponse=JSON.parse(body);
                if(success) return success( jsonResponse );
            } catch(ex) { // bad json
              if(error) return error(ex.toString());
            }
          });

        });

        request.on('socket', function (socket) {
            socket.setTimeout( self.timeout );
            socket.on('timeout', function() {
                request.abort();
                if(timeout) return timeout( new Error('request timed out') );
            });
        });
        request.on('error', function (e) {
          // General error, i.e.
          //  - ECONNRESET - server closed the socket unexpectedly
          //  - ECONNREFUSED - server did not listen
          //  - HPE_INVALID_VERSION
          //  - HPE_INVALID_STATUS
          //  - ... (other HPE_* codes) - server returned garbage
          console.log(e);
          if(error) return error(e);
        });
        request.on('timeout', function () {
          // Timeout happend. Server received request, but not handled it
          // (i.e. doesn't send any response or it took to long).
          // You don't know what happend.
          // It will emit 'error' message as well (with ECONNRESET code).
          req.abort();
          if(timeout) return timeout( new Error('request timed out') );
        });

        self.requestUrl = (this.ssl?'https':'http') + '://' + request._headers['host'] + request.path;
        if(self.debug) {
          console.log("SimpleAPI.Post",self.requestUrl);
        }

        request.write( bodyString );
        request.end();

    } //RequestPost

    return SimpleAPI;

  })();

  module.exports = SimpleAPI

}).call(this);

Usage:

// Parameters
// domain: example.com
// ssl:true, port:80
// timeout: 30 secs
// debug: true
// json response:true
var api = new SimpleAPI('posttestserver.com', 80, 1000 * 10, true, true, true); 

var headers = {
    'Content-Type' : 'application/json',
    'Accept' : 'application/json' 
};
var params = {
  "dir" : "post-test"
};
var method = 'post.php';

api.Post(method, headers, params, body
    , function(response) { // success
       console.log( response );
    }
    , function(error) { // error
      console.log( error.toString() );
    }
    , function(error) { // timeout
       console.log( new Error('timeout error') );
    });

Assuming you have node-inspector installed on your computer (if not, just type 'npm install -g node-inspector') you just have to run:

node-inspector & node --debug-brk scriptFileName.js

And paste the URI from the command line into a WebKit (Chrome / Safari) browser.





node.js http post httprequest