0

When I type somedomain.com/some_api_url?_var1=1 into a browser, the response is {"1":"descriptive string"}, where 1 is a numerical index variable whose value could range from 1 to n. And where "descriptive string" is some text that summarizes what the index represents.

How can I integrate the JSON response from the somedomain.com/some_api_url?_var1=1 api url into the very simple Node.js and Express.js example below?

For testing purposes, the very simple app.js shown below returns "Hello World" when the user requests http : // localhost : 3000 from their web browser. What specific changes need to be made to the code below so that the web browser responds to the request with:

Index is: 1  
Description is:  descriptive string  

instead of responding with "Hello World"?

Here is the current code for app.js:

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

app.get('/', function (req, res) {
    res.send('Hello World!');
});

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

Here is my current attempt, which results in the console printing Got a response: undefined, and with the browser remaining hung up because nothing is returned to the browser as a response:

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

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

    var url = 'somedomain.com/some_api_url?_var1=1';

    http.get(url, function(res){
        var body = '';

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

        res.on('end', function(){
            var fbResponse = JSON.parse(body);
            console.log("Got a response: ", fbResponse.picture);
        });
    }).on('error', function(e){
          console.log("Got an error: ", e);
    });

});

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

The get example code was adapted from the example at this link.

Community
  • 1
  • 1
FarmHand
  • 771
  • 4
  • 10

3 Answers3

1

You actually forgot to return response res.send(data). Change you endpoint code like this. Also use different variable name for internal response object. I am using response here.

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

    var url = 'somedomain.com/some_api_url?_var1=1';

    http.get(url, function(resonse){
         var body = '';

         resonse.on('data', function(chunk){
             body += chunk;
         });

         resonse.on('end', function(){
             var body = JSON.parse(body);
             var text = '';
             for (var key in body){
                  text += 'Index is: ' + key + 
                          '\nDescription is:  ' + body[key] 
             }   

// The Description is:  "descriptive string"  
             console.log("Got a response: ", fbResponse);
             res.send(text);            
         });
    }).on('error', function(e){
        console.log("Got an error: ", e);
    });

});
FarmHand
  • 771
  • 4
  • 10
Zohaib Ijaz
  • 21,926
  • 7
  • 38
  • 60
  • Your code prints `{"1":"descriptive string"}` in the browser and prints `Got a response: undefined` in the console. The OP asks how to format the JSON in a way that allows it to be translated into the simple HTML output that is shown in the OP. How does one alter your code to accomplish this stated goal of the OP? – FarmHand Jun 19 '16 at 19:06
  • The OP asks for the browser to print, on two lines: `Index is: 1 Description is: descriptive string` – FarmHand Jun 19 '16 at 19:09
  • @FarmHand It means that there is no picture attribute in response data. – Zohaib Ijaz Jun 19 '16 at 19:09
  • OK. So we remove the picture component of the code and then add a little code to create a JSON object into which the API response gets passed, then we send the two properties of the new JSON object into some extremely simple HTML to the browser? I am just looking for a working example of this simple end to end translation. – FarmHand Jun 19 '16 at 19:12
  • Your revised code gives the following console printout, indicating that the object is still undefined: `undefined:1 undefined ^ SyntaxError: Unexpected token u at Object.parse (native) at IncomingMessage. (/home/user/nodejs_apps/express_helloworld/myapp/app.js:76:30) at emitNone (events.js:85:20) at IncomingMessage.emit (events.js:179:7) at endReadableNT (_stream_readable.js:913:12) at _combinedTickCallback (node.js:383:13) at process._tickCallback (node.js:407:11)` – FarmHand Jun 19 '16 at 19:41
0

Try this code with express 4.14.0

As @Zohaib-Ijaz pointed out, res is redefined and won't work for the res.send without a rename. This code also calls itself for demo purposes (so you can ignore app.get('/some_api_url', for the moment.

Then once the http.get is done, work with the object and print as you like. Keep in mind this code is not defensive against errors in the JSON.

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

const PORT = 3000;

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

  var url = `http://localhost:${PORT}/some_api_url?_var1=1`;

  http.get(url, function (resInner) {
    var body = '';

    resInner.on('data', function (chunk) {
      body += chunk;
    });

    resInner.on('end', function () {
      var fullResponse = JSON.parse(body); // {"343",:"I've heard 344 is more"}

      // code to pair the keys with their data in plain js
      var indexKeys = Object.keys(fullResponse);
      var replies = indexKeys.map((key) => {
        return `Index is ${key}\nDescription is ${fullResponse[key]}`;
      });

      //note this injection of a <pre> tag is just so modern browsers
      // will respect the newlines. it is not an HTML document or JSON
      res.send(
        `<pre>${replies.join("\n")}</pre>`
      );
    });
  }).on('error', function (e) {
    console.log("Got an error: ", e);
  });

});


app.get('/some_api_url', (req, res) => {
  var var1 = req.query.var1 || "343";
  var value = `I've heard ${parseInt(var1) + 1} is more`;
  var reply = {};
  reply[var1] = value;
  res.send(JSON.stringify(reply));
});

app.listen(PORT, function () {
  console.log(`Example app listening on port ${PORT}!`);
});
user01
  • 891
  • 7
  • 13
  • Thank you. I will try this in a moment when I am done cleaning to prepare. However, at first glance, your code prints an array into the response. How do we alter it to assume that the first variable will always be the index value, and the second variable will always be its description. This would make for more usable code. – FarmHand Jun 19 '16 at 19:20
  • It doesn't print an array; the res.send() gets a string. The string template wraps the joined replies array in a pre tag. This put out exactly what you asked for in the question, assuming you get the standard response (like this express app will give). See how the map handles the keys. Remember, there are no 1st or 2nd in js objects. Just keys and values – user01 Jun 19 '16 at 19:32
0

You seem to be mixing up Express, native HTTP module, and HTTP client.

Here is the serverside code for sending the response you are looking for.

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

// our "database"
var database = ['APPLE', 'BOOK', 'CAT', 'DOG', 'ELEPHANT'];

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

  // apply query parsing only of the query parameter is specified
  if ('itemId' in req.query) {
    var itemId = req.query.itemId;
    // index less than 0 will not yield anything from our "database"
    if (itemId < 0) {
      res.status(400).send('Invalid item id');
    // the item index corresponds to one of the items in the "database"
    } else if (itemId < database.length) {
      var result = 'Index: ' + itemId + '<br>Description: ' + database[itemId];
      res.send(result);
    // index exceeds the size of the array, so nothing will be found
    } else {
      res.status(404).send('Item not found');
    }
  // render the default homepage
  } else {
    res.send('Request format: http://localhost:3000/?itemId=n');
  }

});

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

To see it in action, load http://localhost:3000/?itemId=0 in the browser. Valid itemId values are 0 to 4.

Hage Yaapa
  • 521
  • 3
  • 4
  • I don't think this is what OP wants. OP wants to make an HTTP GET from the server, handle the response from the GET, then return a set of strings. There is no passing of parameters to the root '/' at all – user01 Jun 19 '16 at 19:34