180

I'm looking to use information from an HTTP request using Node.js (i.e. call a remote web service and echo the response to the client).

In PHP I would have used cURL to do this. What is the best practice in Node?

Jeremy
  • 1
  • 85
  • 340
  • 366
slifty
  • 13,062
  • 13
  • 71
  • 109

20 Answers20

111

See the documentation for the HTTP module for a full example:

https://nodejs.org/api/http.html#http_http_request_options_callback

maikthomas
  • 427
  • 5
  • 15
Dan Grossman
  • 51,866
  • 10
  • 112
  • 101
  • 11
    Aslo worth pointing out there's a very popular wrapper library `request.js` https://github.com/mikeal/request – Farzher Nov 10 '12 at 22:27
  • 2
    http request y async, curl is sync. – e-info128 Jul 07 '13 at 00:41
  • 3
    @WHK such is the nature of node.js – slifty Jul 09 '13 at 14:22
  • The big problem i see with this is, that you cant simply enter the URL and get response. You need to separate URL in units to request it. But of curse there probably is a way, it just would be more convinient to use one curl like command for this. – Jānis Gruzis Jun 03 '14 at 07:50
  • 21
    This site can convert your `cURL` command to node.js request: http://curl.trillworks.com/#node – Maxim Mai Jan 13 '16 at 20:34
  • 1
    Welcome to reality: request has been deprecated, see github.com/request/request/issues/3142 Seems to me that http.request has more potential – vintprox May 13 '20 at 15:22
85

The http module that you use to run servers is also used to make remote requests.

Here's the example in their docs:

var http = require("http");

var options = {
  host: 'www.google.com',
  port: 80,
  path: '/upload',
  method: 'POST'
};

var req = http.request(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('BODY: ' + chunk);
  });
});

req.on('error', function(e) {
  console.log('problem with request: ' + e.message);
});

// write data to request body
req.write('data\n');
req.write('data\n');
req.end();
MiniGod
  • 3,683
  • 1
  • 26
  • 27
Jeremy
  • 1
  • 85
  • 340
  • 366
  • 15
    This is very low level compared to the curl-like behavior that the OP asked for. – Dan Dascalescu Feb 27 '13 at 13:01
  • 1
    To All: Nowadays, use `request` - https://www.npmjs.com/package/request - and upvote Nitish's answer, below, which is the better answer in 2018. – Dan Nissenbaum Feb 19 '18 at 23:32
  • 9
    Welcome to reality: request has been deprecated, see https://github.com/request/request/issues/3142 Seems to me that "low-level" operation has more potential than this, because it's not low at all, it's BASIC – vintprox May 13 '20 at 15:20
38

you can easily use request module:

https://www.npmjs.com/package/request

Sample code:

var request = require('request');
request('http://www.google.com', function (error, response, body) {
  if (!error && response.statusCode == 200) {
    console.log(body) // Show the HTML for the Google homepage. 
  }
  else {
    console.log("Error "+response.statusCode)
  }
})
Tomáš Zato
  • 50,171
  • 52
  • 268
  • 778
Nitish Agarwal
  • 692
  • 1
  • 6
  • 16
33

Since looks like node-curl is dead, I've forked it, renamed, and modified to be more curl like and to compile under Windows.

node-libcurl

Usage example:

var Curl = require( 'node-libcurl' ).Curl;

var curl = new Curl();

curl.setOpt( Curl.option.URL, 'www.google.com' );
curl.setOpt( 'FOLLOWLOCATION', true );

curl.on( 'end', function( statusCode, body, headers ) {

    console.info( statusCode );
    console.info( '---' );
    console.info( body.length );
    console.info( '---' );
    console.info( headers );
    console.info( '---' );
    console.info( this.getInfo( Curl.info.TOTAL_TIME ) );

    this.close();
});

curl.on( 'error', function( err, curlErrorCode ) {

    console.error( err.message );
    console.error( '---' );
    console.error( curlErrorCode );

    this.close();

});

curl.perform();

Perform is async, and there is no way to use it synchronous currently (and probably will never have).

It's still in alpha, but this is going to change soon, and help is appreciated.

Now it's possible to use Easy handle directly for sync requests, example:

var Easy = require( 'node-libcurl' ).Easy,
    Curl = require( 'node-libcurl' ).Curl,
    url = process.argv[2] || 'http://www.google.com',
    ret, ch;

ch = new Easy();

ch.setOpt( Curl.option.URL, url );

ch.setOpt( Curl.option.HEADERFUNCTION, function( buf, size, nmemb ) {

    console.log( buf );

    return size * nmemb;
});

ch.setOpt( Curl.option.WRITEFUNCTION, function( buf, size, nmemb ) {

    console.log( arguments );

    return size * nmemb;
});

// this call is sync!
ret = ch.perform();

ch.close();

console.log( ret, ret == Curl.code.CURLE_OK, Easy.strError( ret ) );

Also, the project is stable now!

jonathancardoso
  • 11,737
  • 7
  • 53
  • 72
  • I tried installing both node-curl and node-libcurl, but both give me the same message: "Cannot find curl's header file." This is during the `node tools/retrieve-win-deps && node tools/generate-stubs && node-gyp rebuild` step. Any thoughts? – SaganRitual May 05 '15 at 20:04
  • @GreatBigBore you need libcurl devel package installed on your machine. If you are using debian for example, you can install it with ``$ apt-get install libcurl4-openssl-dev`` – jonathancardoso May 06 '15 at 13:12
  • 1
    can you use the `-L` option somehow? – corvid May 10 '15 at 02:39
  • 2
    Yes: [CURLOPT_FOLLOWLOCATION](http://curl.haxx.se/libcurl/c/CURLOPT_FOLLOWLOCATION.html), with node-libcurl you are going to use ``curl.setOpt( 'FOLLOWLOCATION', true );``. Btw, questions like that are better suited to the [issue tracker](https://github.com/JCMais/node-libcurl/issues) than this comment section. ;) – jonathancardoso May 10 '15 at 03:28
  • I did not manage to install `node-libcurl` on Ubuntu 20_04 due to dependency issue with `node-pre-gyp` and `node v15`. So a [lower node version](https://stackoverflow.com/a/49106657/1705829) can help but what about the `apt` dependencies. – Timo Aug 01 '21 at 07:37
  • @SaganRitual did you get any further? See my comment to this post and [here](https://stackoverflow.com/questions/49101266/cant-install-node-libcurl-on-debian#comment121249552_49106657) as well. Seems like I need a lower Ubuntu version. – Timo Aug 01 '21 at 07:40
30

EDIT:

For new projects please refrain from using request, since now the project is in maitainance mode, and will eventually be deprecated

https://github.com/request/request/issues/3142

Instead i would recommend Axios, the library is in line with Node latest standards, and there are some available plugins to enhance it, enabling mock server responses, automatic retries and other features.

https://github.com/axios/axios

const axios = require('axios');

// Make a request for a user with a given ID
axios.get('/user?ID=12345')
  .then(function (response) {
    // handle success
    console.log(response);
  })
  .catch(function (error) {
    // handle error
    console.log(error);
  })
  .then(function () {
    // always executed
  });

Or using async / await:

try{
    const response = await axios.get('/user?ID=12345');
    console.log(response)
} catch(axiosErr){
    console.log(axiosErr)
}

I usually use REQUEST, its a simplified but powerful HTTP client for Node.js

https://github.com/request/request

Its on NPM npm install request

Here is a usage sample:

var request = require('request');

request('http://www.google.com', function (error, response, body) {
   if (!error && response.statusCode == 200) {
       console.log(body) // Show the HTML for the Google homepage.
   }
})
Aronis Mariano
  • 2,352
  • 3
  • 22
  • 19
9

well if you really need a curl equivalent you can try node-curl

npm install node-curl

you will probably need to add libcurl4-gnutls-dev.

Florent
  • 12,310
  • 10
  • 49
  • 58
warfares
  • 99
  • 1
  • 1
8

The above examples work but don't go so far as to really deal with a real world example (i.e. when you process data coming in multiple chunks. One thing you need to make sure of is that you have an 'on chunk' handler that push's the data into an array (fastest way to do this in JS) and an 'on end' handler that joins them all together so you can return it.

This is especially necessary when you're working with big requests (5000+ lines) and the server sends a bunch of data at you.

Here's an example in one of my programs (coffeescript): https://gist.github.com/1105888

Brad Dickason
  • 492
  • 4
  • 10
7

How about for example https://github.com/joyent/node/wiki/modules#wiki-tcp. A very quick summary =>

Omar Dulaimi
  • 846
  • 10
  • 30
Alfred
  • 60,935
  • 33
  • 147
  • 186
5

In Node.js 18 you can use directly fetch

const res = await fetch('https://nodejs.org/api/documentation.json');
if (res.ok) {
  const data = await res.json();
  console.log(data);
}
  • Actually it isn't working in many cases because of CORS. (maybe modejs.org working) That is the reason why you need to use curl. – kepes Nov 24 '22 at 09:07
4

There is npm module to make a curl like request, npm curlrequest.

Step 1: $npm i -S curlrequest

Step 2: In your node file

let curl = require('curlrequest')
let options = {} // url, method, data, timeout,data, etc can be passed as options 
curl.request(options,(err,response)=>{
// err is the error returned  from the api
// response contains the data returned from the api
})

For further reading and understanding, npm curlrequest

Laksh Goel
  • 169
  • 1
  • 12
4

Here is a standard lib (http) async / await solution.

const http = require("http");

const fetch = async (url) => {
  return new Promise((resolve, reject) => {
    http
      .get(url, (resp) => {
        let data = "";
        resp.on("data", (chunk) => {
          data += chunk;
        });
        resp.on("end", () => {
          resolve(data);
        });
      })
      .on("error", (err) => {
        reject(err);
      });
  });
};

Usage:

await fetch("http://example.com");
Glen Thompson
  • 9,071
  • 4
  • 54
  • 50
3

Use request npm module and after call

var request = require('request');
request('http://www.google.com', function (error, response, body) {
  console.log('error:', error); // Print the error if one occurred
  console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
  console.log('body:', body); // Print the HTML for the Google homepage.
});

For best practice also use some winston logger module or else simple console.log and then run your application like

npm start output.txt 

Result of above command will generate one txt file on root with all data which you have printed in console.log

D M Patel
  • 86
  • 4
2

Uses reqclient, it's a small client module on top of request that allows you to log all the activity with cURL style (optional, for development environments). Also has nice features like URL and parameters parsing, authentication integrations, cache support, etc.

For example, if you create a client object an do a request:

var RequestClient = require("reqclient").RequestClient;
var client = new RequestClient({
        baseUrl:"http://baseurl.com/api/v1.1",
        debugRequest:true, debugResponse:true
    });

var resp = client.post("client/orders", {"client":1234,"ref_id":"A987"}, {headers: {"x-token":"AFF01XX"}})

It will log within the console something like this:

[Requesting client/orders]-> -X POST http://baseurl.com/api/v1.1/client/orders -d '{"client": 1234, "ref_id": "A987"}' -H '{"x-token": "AFF01XX"}' -H Content-Type:application/json
[Response   client/orders]<- Status 200 - {"orderId": 1320934}

The request will return a Promise object, so you have to handle with then and catch what to do with the result.

reqclient is available with npm, you can install the module with: npm install reqclient.

Mariano Ruiz
  • 4,314
  • 2
  • 38
  • 34
1

I ended up using the grunt-shell library.

Here is my source gist for my fully implemented Grunt task for anyone else thinking about working with the EdgeCast API. You'll find in my example that I use a grunt-shell to execute the curl command which purges the CDN.

This was that I ended up with after spending hours trying to get an HTTP request to work within Node. I was able to get one working in Ruby and Python, but did not meet the requirements of this project.

1

You can try using POSTMAN Chrome app for your request and you can generate node js code from there

Ravi Teja
  • 161
  • 1
  • 8
1

I had a problem sending POST data to cloud DB from IOT RaspberryPi, but after hours I managed to get it straight.

I used command prompt to do so.

sudo curl --URL http://<username>.cloudant.com/<database_name> --user <api_key>:<pass_key> -X POST -H "Content-Type:application/json" --data '{"id":"123","type":"987"}'

Command prompt will show the problems - wrong username/pass; bad request etc.

--URL database/server location (I used simple free Cloudant DB) --user is the authentication part username:pass I entered through API pass -X defines what command to call (PUT,GET,POST,DELETE) -H content type - Cloudant is about document database, where JSON is used --data content itself sorted as JSON

Rudolfs
  • 11
  • 1
1

Request npm module Request node moulde is good to use, it have options settings for get/post request plus it is widely used in production environment too.

Indrani Sen
  • 287
  • 4
  • 19
1

You can use request npm module . Super simple to use. Request is designed to be the simplest way possible to make http calls. It supports HTTPS and follows redirects by default.

var request = require('request');
request('http://www.google.com', function (error, response, body) {
  console.log('error:', error); // Print the error if one occurred
  console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
  console.log('body:', body); // Print the HTML for the Google homepage.
});
Rubin bhandari
  • 1,873
  • 15
  • 20
0

You might want to try using something like this

curl = require('node-curl');
curl('www.google.com', function(err) {
  console.info(this.status);
  console.info('-----');
  console.info(this.body);
  console.info('-----');
  console.info(this.info('SIZE_DOWNLOAD'));
});
Gautam Anand
  • 19
  • 1
  • 3
0

Just a thought, if you really want to treat it as cURL request (ie. you just want to check if the page is up or not) you could use (edited from @Glen Thompson answer):

const http = require("http");

function isSiteUp(url) {
  return new Promise((resolve, reject) => {
    http.get(url, (res) => {
      if (!err && res.statusCode == 200) {
        resolve(true);
      } else {
        console.log(err);
        resolve(false);
      }
    })
    .on("error", (err) => {
      reject(err);
    });
  });
}
Nienaber
  • 101
  • 1
  • 2
  • 12