1011

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

Adam Grant
  • 10,123
  • 9
  • 51
  • 65
Mark
  • 57,724
  • 41
  • 114
  • 149
  • 16
    As suggested in [Jed Watson's answer](http://stackoverflow.com/a/12999483/742156), I'd strongly recommend using [request](https://github.com/mikeal/request) unless you're writing a low-level API. – namuol May 31 '13 at 09:09
  • 5
    You could just use `node-fetch` which is an implementation of the native `fetch` JavaScript method to make HTTP requests. – Fez Vrasta Aug 13 '16 at 08:23
  • This post covers the basic use scenarios for using request. http://blog.modulus.io/node.js-tutorial-how-to-use-request-module – Shaswat Rungta Nov 24 '16 at 09:41
  • Possible duplicate of [Steps to send a https request to a rest service in Node js](http://stackoverflow.com/questions/13121590/steps-to-send-a-https-request-to-a-rest-service-in-node-js) – Abhijeet Apr 27 '17 at 04:16
  • 3
    The request module recommended in a comment above is [**deprecated** now](https://github.com/request/request/issues/3142) – electrovir Jun 10 '20 at 13:54
  • Alternatives to `request` https://github.com/request/request/issues/3143 – Simon_Weaver Jul 10 '20 at 22:38
  • They are still updating request, and there's no good alternatives. – stackers Feb 23 '21 at 00:01

21 Answers21

1170

request is now deprecated. It is recommended you use an alternative

In no particular order and dreadfully incomplete:

Stats comparision Some code examples

Original answer:

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

Michael Schnerring
  • 3,354
  • 3
  • 19
  • 52
Jed Watson
  • 19,372
  • 3
  • 31
  • 42
  • 2
    My program doesn't actually send the http request post when I keep the function handling errors. Once I deleted it, it worked. Your link also doesn't include the error handling. Perhaps this is the newest version. – krikara Dec 06 '13 at 09:43
  • 159
    { form: { key: 'value' } } should be replaced by { json: { key: 'value' } } (as the question is not specific to forms). One also have to understand 'form' and 'json' are request library keywords and not part of the custom data (as trivial as this last comment could appear, it took me some time to figure it...) – blacelle Mar 19 '14 at 12:04
  • this is probably the best lib by now. You can do pretty much anything you wan – disklosr Mar 25 '14 at 16:24
  • 1
    @bla Thanks for that comment, was struggeling to figure out why it didn't work properly since it didn't indicate that `form:` or `json:` was a keyword. – Shaun Groenewald Apr 09 '14 at 09:43
  • Is there any way to ignore content-length in a GET request with the request module ? If the content-length in header doesn't match the real length, it throws an error – Rayjax Apr 17 '14 at 06:45
  • I have tried this library, she can't get the set-cookie from the response header while a simple wget can. – Dimitri Kopriwa Dec 11 '14 at 14:04
  • 8
    I keep coming back to this question and answer. It really should be "the" answer to the question. – Spencer Kormos Dec 21 '15 at 00:58
  • 7
    You deserve a golden badge purely for this answer. It's so much more useful than the accepted one...and it already existed back in 2012? Wow – Zoltán Schmidt Mar 20 '16 at 02:04
  • Just here to point out that request lib wont be a good choice if we want to implement things like progress bars on the frontend. native is better in those kind of cases. – Amin Mohamed Ajani May 04 '16 at 12:23
  • 3
    you may need to add dependency by running this command 'npm install --save request' – Shady Mohamed Sherif Jun 02 '16 at 21:15
  • how do u modify this to get a large response back from the post request . if my response string length is huge i get a buffer tostring failed exception – vardha Oct 25 '16 at 15:58
  • 1
    @bla, how the hell is the 'json' keyword not mentioned ANYWHERE in their documentation?! Ridiculous. Thank you so much for that comment. – Kyle Baker Feb 07 '17 at 05:38
  • Agree with Kyle Baker... I've been using response.get() to read web page so naturally I figured there was a response.put() or response.post() call.. However when searching for either one, I come up empty. Thanks for this. – bob Feb 04 '18 at 17:12
  • What if this call needs to be made through a proxy? – Kermit_ice_tea Jun 25 '18 at 23:24
  • Request can't handle HTTP errors properly : If you get a statusCode 500 you need to manage the thing yourself : if resp.statusCode === 500, and so you have to manage every error case.... I don't like it much since the error object is null in that case... – Deunz Mar 25 '19 at 16:17
  • 34
    This library has been deprecated. – Evorlor Feb 15 '20 at 22:14
  • 1
    As an alternative, check out Axios, it's the same thing done in promises :) – Ben Botvinick Apr 01 '20 at 15:22
  • Thank you for the post it helped me a lot after spending a lot of time searching for solution. – jazeb007 Apr 08 '20 at 19:38
  • 2
    @Jazeb_007 Its been deprecated. You should avoid it. – codingbryan May 08 '20 at 13:58
900

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.

fangzhzh
  • 1,655
  • 17
  • 24
onteria_
  • 60,174
  • 6
  • 66
  • 62
  • sure it's an example but don't hardcore code into strings, just use a bit of `fs.read` instead. – Raynos May 28 '11 at 13:05
  • 4
    Is the content-length header calculated correctly? Supposed to be bytes, right? – Eric Aug 14 '13 at 17:55
  • 7
    Note that `querystring.stringify()` [doesn't support nested objects](https://github.com/joyent/node/issues/1665), so you might want to use [`qs.stringify()`](https://npmjs.org/package/qs) instead. – johndodo Dec 20 '13 at 09:54
  • 54
    `Content-Length` is bytes and not necessarily string length (UTF-16 etc). Using `Buffer.byteLength(data)` will always be correct. – greenimpala Jan 15 '14 at 10:55
  • It would likely be best if you had something such as the following: https://gist.github.com/anonymous/8444968 ( sorry, tried to include in comment, but it wasn't readable ) on.data is used to receive chunks, and on.end is when you have them all. Deal with larger sets of data, and you will run into this issue. – conrad10781 Jan 15 '14 at 21:24
  • some times you may need to send **RAW data**, for instance, I was getting a response **"invalid JSON string"** from the server. so I used `post_req.write('{"id": "1", "name": "name", "type": "type"}');`, also removed 'Content-Length' from header – Midhun KM Mar 06 '14 at 06:25
  • 4
    for sending standard postdata, the object in `querystring.stringify` should be your own data object, not the junk that is displayed in this answer (which may be useful for file based objects?). I was stuck on that for ages... http://stackoverflow.com/questions/9768192/sending-data-through-post-request-from-a-node-js-server-to-a-node-js-server provided my complete solution – RozzA Nov 06 '14 at 10:55
  • Mine was not working for many hours, until I put in "Content-Length". It seems required. – Amin Ariana Feb 23 '16 at 23:22
  • 8
    Gotcha: If you are using an ssl-encrypted site, you will need the "https" library. You can't just change the port to 443. – Dave Collins Apr 02 '16 at 20:47
  • 1
    I'M FINDING THIS ANSWER TO BE EXCEDINGLY OUT OF DATE. Options doesn't have `host`, `port`, `path`, ... Check the API / Options section of https://github.com/ranm8/requestify – Steve Apr 09 '17 at 19:02
  • 1
    thank you for an answer that does not suggest adding a 3rd party library just to make an HTTP request – Jordan Sitkin May 30 '17 at 21:01
  • Why would post_data be a query string? I think this should not be the accepted answer. I can't tell if it's just wrong or a weird use-case. Haven't tested with closure compiler but submitting actual JSON would be a better example. IMO, this answer is misleading. – rm.rf.etc Aug 31 '17 at 17:12
  • no need for extra modules... `const { URLSearchParams } = require('url');` – Endless Nov 27 '17 at 17:21
  • why should set up the request before write post data into it? Set up request doesn't mean executing it here? – David Wei Dec 05 '17 at 17:11
  • @DavidWei correct, think of it in terms of sockets, when you create the request you are creating a socket, then you write to that socket – Purefan Sep 19 '18 at 11:33
  • I'm not sure why the options `host`, `port` etc are all given separately, because it's perfectly fine to just pass a URL: `http.request('http://some-host.com/path', options, callback)` – jlh Apr 12 '21 at 09:36
139

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);
});
RaviStrs
  • 354
  • 3
  • 9
Josiah Choi
  • 1,749
  • 1
  • 10
  • 9
  • After review in their documentation. it states the following: json - sets body but to JSON representation of value and adds Content-type: application/json header. Additionally, parses the response body as JSON. That means when json = true, it will set header and json and body. Otherwise, no header set, and parse as text. (Like the above XML example). That makes the request API handy and simplistic but quite hard to understand at first time. – Josiah Choi Mar 16 '15 at 06:59
  • It is technically in their docs, but none of the examples show it--only form data. It's a needle in the haystack, and as such, it's a huge ommission, since this is the second most frequent way I use ajax in JS, ever, and certainly one of the most common on the web. – Kyle Baker Feb 07 '17 at 19:24
  • Using request.post is IMO somewhat nicer than specifying POST as the method. Here are some [examples from GitHub for using request.post](https://www.codota.com/code/javascript/functions/request/RequestAPI/post) – drorw Apr 18 '19 at 20:31
  • 17
    This library has been deprecated. – Evorlor Feb 15 '20 at 22:14
56

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:

async function main() {
    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',
        })
    })
}

main().catch(err => {
    console.log(err)
})
mpen
  • 237,624
  • 230
  • 766
  • 1,119
  • What is `write` method on `req,write()` is used for? – Ari Dec 29 '19 at 14:03
  • 1
    @Ari That writes the body of the request... https://nodejs.org/api/http.html#http_request_write_chunk_encoding_callback – mpen Dec 29 '19 at 21:30
  • Thanks, this one is really suitable for aws lambda as now it always requires async await to work with. – Tuananhcwrs Aug 20 '20 at 03:42
  • 1
    @mpen did you ever run this code ? It looks like the request example has wrong order of parameters. – Mozart Brocchini Sep 01 '20 at 17:08
  • @MozartBrocchini Yes, I ran it. [Look at the docs](https://nodejs.org/api/https.html#https_https_request_url_options_callback), this is using the `https.request(options[, callback])` form. – mpen Sep 01 '20 at 17:46
  • @mpen thanks for the quick answer, I got that, I was talking about the parameters of function you wrote `httpPost` , this takes a `body` parameter then an `options` as a 2nd parameter, it looks like your _Usage:_ code is passing options 1st parameter, then body as 2nd arg, did I miss something ? – Mozart Brocchini Sep 02 '20 at 13:38
  • 1
    @MozartBrocchini Yes, you missed the curly braces :-) I'm using *object destructuring*. – mpen Sep 02 '20 at 23:35
  • That gives me an error `SyntaxError: await is only valid in async function` – Christian Oct 07 '20 at 15:57
  • @Christian Yuppers. You should put it in an async function ;) – mpen Oct 08 '20 at 06:50
46

I use Restler and Needle for production purposes. They are both much more powerful than native httprequest. It is possible to request with basic authentication, special header entry or even upload/download files.

As for post/get operation, they also are much simpler to use than raw ajax calls using httprequest.

needle.post('https://my.app.com/endpoint', {foo:'bar'}, 
    function(err, resp, body){
        console.log(body);
});
Grant Li
  • 933
  • 9
  • 8
  • I tried request, node-form-data and superagent before needle. needle was the only one that worked correctly for me when trying to do a multipart form file upload. – Paul Young Aug 08 '13 at 16:42
37

There are dozens of open-source libraries available that you can use to making an HTTP POST request in Node.

1. Axios (Recommended)

const axios = require('axios');

const data = {
    name: 'John Doe',
    job: 'Content Writer'
};

axios.post('https://reqres.in/api/users', data)
    .then((res) => {
        console.log(`Status: ${res.status}`);
        console.log('Body: ', res.data);
    }).catch((err) => {
        console.error(err);
    });

2. Needle

const needle = require('needle');

const data = {
    name: 'John Doe',
    job: 'Content Writer'
};

needle('post', 'https://reqres.in/api/users', data, {json: true})
    .then((res) => {
        console.log(`Status: ${res.statusCode}`);
        console.log('Body: ', res.body);
    }).catch((err) => {
        console.error(err);
    });

3. Request

const request = require('request');

const options = {
    url: 'https://reqres.in/api/users',
    json: true,
    body: {
        name: 'John Doe',
        job: 'Content Writer'
    }
};

request.post(options, (err, res, body) => {
    if (err) {
        return console.log(err);
    }
    console.log(`Status: ${res.statusCode}`);
    console.log(body);
});

4. Native HTTPS Module

const https = require('https');

const data = JSON.stringify({
    name: 'John Doe',
    job: 'Content Writer'
});

const options = {
    hostname: 'reqres.in',
    path: '/api/users',
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Content-Length': data.length
    }
};


const req = https.request(options, (res) => {
    let data = '';

    console.log('Status Code:', res.statusCode);

    res.on('data', (chunk) => {
        data += chunk;
    });

    res.on('end', () => {
        console.log('Body: ', JSON.parse(data));
    });

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

req.write(data);
req.end();

For details, check out this article.

attacomsian
  • 1,430
  • 15
  • 16
22

Update 2020:

I've been really enjoying phin - The ultra-lightweight Node.js HTTP client

It can be used in two different ways. One with Promises (Async/Await) and the other with traditional callback styles.

Install via: npm i phin

Straight from it's README with await:

const p = require('phin')

await p({
    url: 'https://ethanent.me',
    method: 'POST',
    data: {
        hey: 'hi'
    }
})


Unpromisifed (callback) style:

const p = require('phin').unpromisified

p('https://ethanent.me', (err, res) => {
    if (!err) console.log(res.body)
})

As of 2015 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');
Levi Roberts
  • 1,160
  • 3
  • 18
  • 42
  • 1
    Another one I found that looks pretty good is https://github.com/request/request which seems a bit more popular than unirest at least as of this writing – Lochlan Jul 28 '15 at 20:26
  • I can attest to request. It is a very good library. I find that request provides more low level functionality so it's appropriate to use it for specific applications. When I don't necessarily care about the low level stuff, I find Unirest to be adequate. – Levi Roberts Aug 01 '15 at 00:41
  • Why would unirest be considered lightweight when it depends on request? Request itself has 22 dependencies, I don't see how this is lightweight – sigmawf Mar 18 '18 at 01:49
  • @raphadko I'm sure that over the years feature bloat has occurred. Be sure to check the timestamp of when I posted my answer ;) – Levi Roberts Oct 07 '19 at 09:10
21

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();
    });
ranm8
  • 1,025
  • 10
  • 10
18
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);
});
Giulio Roggero
  • 1,632
  • 1
  • 16
  • 11
15

This is the simplest way I use to make request: using 'request' module.

Command to install 'request' module :

$ npm install request

Example code:

var request = require('request')

var options = {
  method: 'post',
  body: postData, // Javascript object
  json: true, // Use,If you are sending JSON data
  url: url,
  headers: {
    // Specify headers, If any
  }
}

request(options, function (err, res, body) {
  if (err) {
    console.log('Error :', err)
    return
  }
  console.log(' Body :', body)

});

You can also use Node.js's built-in 'http' module to make request.

aleung
  • 7,829
  • 3
  • 49
  • 63
Piyush Sagar
  • 2,241
  • 19
  • 26
12

I like the simplicity of superagent (https://github.com/visionmedia/superagent). Same API on both node and browser.

;(async function() {
  var response = await superagent.post('http://127.0.0.1:8125/', {age: 2})
  console.log(response)
})

There is also node-fetch (https://www.npmjs.com/package/node-fetch), which has an API that matches fetch from the browsers - however this requires manual query string encoding, does not automatically handle content types, or so any of the other work superagent does.

mikemaccana
  • 81,787
  • 73
  • 317
  • 396
Pascal Belloncle
  • 10,538
  • 3
  • 53
  • 56
  • 1
    And in contrast to needle, unirest and co, it deliveres on being lightweight (superagent: 16k, unirest: 1M, needle: 530K) – Lars Jan 18 '18 at 09:32
9

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((response) => console.log(response))
      .catch((error) => console.log(error));

OR

await axios.post('/user', {firstName: 'Fred',lastName: 'Flintstone'})
Pujan
  • 2,792
  • 3
  • 33
  • 45
6

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)
               }
    );
5

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') );
    });
loretoparisi
  • 12,864
  • 9
  • 78
  • 108
4

I found a video which explains on how to achieve this: https://www.youtube.com/watch?v=nuw48-u3Yrg

It uses default "http" module together with "querystring" and "stringbuilder" modules. The application takes two numbers (using two textboxes) from a web page and upon submit, returns sum of those two (along with persisting the values in the textboxes). This is the best example I could find anywhere else.

var http = require("http");
var qs = require("querystring");
var StringBuilder = require("stringbuilder");

var port = 9000;

function getCalcHtml(req, resp, data) {
    var sb = new StringBuilder({ newline: "\r\n" });
    sb.appendLine("<html>");
    sb.appendLine(" <body>");
    sb.appendLine("     <form method='post'>");
    sb.appendLine("         <table>");
    sb.appendLine("             <tr>");
    sb.appendLine("                 <td>Enter First No: </td>");

    if (data && data.txtFirstNo) {
        sb.appendLine("                 <td><input type='text' id='txtFirstNo' name='txtFirstNo' value='{0}'/></td>", data.txtFirstNo);
    }
    else {
        sb.appendLine("                 <td><input type='text' id='txtFirstNo' name='txtFirstNo' /></td>");
    }

    sb.appendLine("             </tr>");
    sb.appendLine("             <tr>");
    sb.appendLine("                 <td>Enter Second No: </td>");

    if (data && data.txtSecondNo) {
        sb.appendLine("                 <td><input type='text' id='txtSecondNo' name='txtSecondNo' value='{0}'/></td>", data.txtSecondNo);
    }
    else {
        sb.appendLine("                 <td><input type='text' id='txtSecondNo' name='txtSecondNo' /></td>");
    }

    sb.appendLine("             </tr>");
    sb.appendLine("             <tr>");
    sb.appendLine("                 <td><input type='submit' value='Calculate' /></td>");
    sb.appendLine("             </tr>");

    if (data && data.txtFirstNo && data.txtSecondNo) {
        var sum = parseInt(data.txtFirstNo) + parseInt(data.txtSecondNo);
        sb.appendLine("             <tr>");
        sb.appendLine("                 <td>Sum: {0}</td>", sum);
        sb.appendLine("             </tr>");
    }

    sb.appendLine("         </table>");
    sb.appendLine("     </form>")
    sb.appendLine(" </body>");
    sb.appendLine("</html>");
    sb.build(function (err, result) {
        resp.write(result);
        resp.end();
    });
}

function getCalcForm(req, resp, data) {
    resp.writeHead(200, { "Content-Type": "text/html" });
    getCalcHtml(req, resp, data);
}

function getHome(req, resp) {
    resp.writeHead(200, { "Content-Type": "text/html" });
    resp.write("<html><html><head><title>Home</title></head><body>Want to some calculation? Click <a href='/calc'>here</a></body></html>");
    resp.end();
}

function get404(req, resp) {
    resp.writeHead(404, "Resource Not Found", { "Content-Type": "text/html" });
    resp.write("<html><html><head><title>404</title></head><body>404: Resource not found. Go to <a href='/'>Home</a></body></html>");
    resp.end();
}

function get405(req, resp) {
    resp.writeHead(405, "Method not supported", { "Content-Type": "text/html" });
    resp.write("<html><html><head><title>405</title></head><body>405: Method not supported</body></html>");
    resp.end();
}

http.createServer(function (req, resp) {
    switch (req.method) {
        case "GET":
            if (req.url === "/") {
                getHome(req, resp);
            }
            else if (req.url === "/calc") {
                getCalcForm(req, resp);
            }
            else {
                get404(req, resp);
            }
            break;
        case "POST":
            if (req.url === "/calc") {
                var reqBody = '';
                req.on('data', function (data) {
                    reqBody += data;
                    if (reqBody.length > 1e7) { //10MB
                        resp.writeHead(413, 'Request Entity Too Large', { 'Content-Type': 'text/html' });
                        resp.end('<!doctype html><html><head><title>413</title></head><body>413: Request Entity Too Large</body></html>');
                    }
                });
                req.on('end', function () {
                    var formData = qs.parse(reqBody);
                    getCalcForm(req, resp, formData);
                });
            }
            else {
                get404(req, resp);
            }
            break;
        default:
            get405(req, resp);
            break;
    }
}).listen(port);
user203687
  • 6,223
  • 10
  • 46
  • 78
4

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
    });

}
manyu
  • 91
  • 1
  • 7
4

Axios is a promise based HTTP client for the browser and Node.js. Axios makes it easy to send asynchronous HTTP requests to REST endpoints and perform CRUD operations. It can be used in plain JavaScript or with a library such as Vue or React.

const axios = require('axios');

        var dataToPost = {
          email: "your email",
          password: "your password"
        };

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

        axios.post('endpoint or url', dataToPost, axiosConfiguration)
        .then((res) => {
          console.log("Response: ", res);
        })
        .catch((err) => {
          console.log("error: ", err);
        })
abhinavxeon
  • 894
  • 5
  • 17
3
let request = require('request');
let jsonObj = {};
request({
    url: "https://myapii.com/sendJsonData",
    method: "POST",
    json: true,
    body: jsonObj
    }, function (error, resp, body){
       console.log(resp);
});

Or you could use this library:

let axios = require("axios");
let jsonObj = {};

const myJsonAPI = axios.create({
   baseURL: 'https://myapii.com',
   timeout: 120*1000
});

let response = await myJsonAPI.post("sendJsonData",jsonobj).catch(e=>{
    res.json(e);
});
console.log(response);
Skere
  • 345
  • 1
  • 14
Jitendra virani
  • 326
  • 4
  • 8
2

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

var postData = {
  email: "test@test.com",
  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);
})
Matthew Rideout
  • 4,311
  • 1
  • 24
  • 46
0

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)
            }
        });
Darryl RN
  • 3,837
  • 1
  • 16
  • 28
Shashwat Gupta
  • 3,139
  • 23
  • 21
0

Request-Promise Provides promise based response. http response codes other than 2xx will cause the promise to be rejected. This can be overwritten by setting options.simple = false

var options = {
  method: 'POST',
  uri: 'http://api.posttestserver.com/post',
  body: {
  some: 'payload'
 },
  json: true // Automatically stringifies the body to JSON
};

rp(options)
.then(function (parsedBody) {
    // POST succeeded...
})
.catch(function (err) {
    // POST failed...
});
veeresh yh
  • 749
  • 7
  • 18