Joelster
Joelster

Reputation: 349

In a Nodejs app how do I make an HTTP client request inside an Express method

When a browser or curl client calls my node express app, I want to fetch JSON data from an external website and return it, however despite seeing the nested http call return the JSON data back to my express server I'm battling to get the JSON to return to the calling browser - how do I do this?

Here is the current test app code with curl response:

var http = require('http');
var app = require('express')();

app.get('/', function (req, res) {

  var str = '';

  var options = {
    host: 'jsonplaceholder.typicode.com',
    path: '/posts/1'
  };

  callback = function(response) {
    response.on('data', function (chunk) {
      str += chunk;
    });

    response.on('end', function () {
      console.log(str);
    });
  }

  var req = http.request(options, callback);

  res.send(str);
  req.end();
});

app.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});

Here is the result of CURL localhost:3000 (no body data returned): enter image description here

The server side console log's show the http request data has been received: enter image description here

All suggestions/pointers appreciated!

Upvotes: 5

Views: 11367

Answers (2)

m-a-r-c-e-l-i-n-o
m-a-r-c-e-l-i-n-o

Reputation: 2672

It appears that you need to wait for the nested response to come back before sending out the actual response, like so:

app.get('/', function (req, res) {

  var str = '';

  var options = {
    host: 'jsonplaceholder.typicode.com',
    path: '/posts/1'
  };

  var callback = function(response) {
    response.on('data', function (chunk) {
      str += chunk;
    });

    response.on('end', function () {
      console.log(str);
      res.send(str); // SEND ACTUAL RESPONSE HERE
    });
  }

  var req = http.request(options, callback);
  req.end();

});

Otherwise, you are sending str right away and it's empty, thus why you can't see it.

Upvotes: 6

robertklep
robertklep

Reputation: 203534

Just as an alternative (the answer provided by m-a-r-c-e-l-i-n-o will work just fine), you can shorten your code (and save a bit of memory) by using the streams provided by both Express and http.request(), like this:

app.get('/', function(req, res) {
  http.request('http://jsonplaceholder.typicode.com/posts/1', function(response) {
    response.pipe(res);
  }).on('error', function(e) {
    res.sendStatus(500);
  }).end();
});

Upvotes: 10

Related Questions