Search code examples
node.jsexpressrequestnode-https

Node - Making a call to an ExpressJS route, and need to do a GET request to an API in it


I'm making a cryptocurrency dashboard for a project, and I'm completely new to Node and Express. This is what I have currently

app.get('/search', function(req,res){
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.write(req.url);
    data = []
    var options = {
        "method": "GET",
        "hostname": "rest.coinapi.io",
        "path": "/v1/assets",
        "headers": {'X-CoinAPI-Key': 'MY_API_KEY_HERE'}
    };

    const request = https.request(options, (data, response) => {    
        response.on('data', d => {
            data.push(d);
        })
    });
    console.log(data);
    request.end();
    res.end();
})

The idea is on my front end, I have a button that when clicked, will make a request to the CoinAPI api, getting all reported assets and current values. I'm not quite sure how I'm supposed to send that response data back to my frontend as a response. So, I tried to pull the response data out of the JSON that gets returned by the https.request line. I have a data array data = [] as you can see at the top of my code.

I originally had my request set up like:

const request = https.request(options, response => { 

but when I would try to push d onto data, I console logged and the data array was empty. This makes sense, the data array is out of scope of the request function, so data doesn't get updated. But when I tried to pass data into the function, I errored out.

Basically I want to be able to send the JSON data back to my front end after making the request to CoinAPI. If I do process.stdout.write(d) in my https.request callback, I do actually see the coinapi data coming back. I just don't know how to send it to the front end as part of my response.


Solution

  • Issues:

    • The use of (data, response) is incorrect. The first and only argument is response so it should be (response).

    • The on('data') event receives buffered data. Concatenating it to a final string is the standard usage, not appending an array.

    • You're missing an on('end') which you should use to output the final data or do any processing.

    • Using res.write you're sending a text/html content type and some content which you don't want if the goal is to output JSON which the frontend can parse and use.

    • Missing an error handler for the API call.

    Complete updated code:

    app.get('/search', function(req,res){
      let str = '';
      const options = {
        "method": "GET",
        "hostname": "rest.coinapi.io",
        "path": "/v1/assets",
        "headers": {'X-CoinAPI-Key': 'MY_API_KEY_HERE'}
      };
    
      const request = https.request(options, (response) => {
          response.on('data', d => {
            str += d;
          });
          response.on('end', () => {
            try {
              let obj = JSON.parse(str);
              // do any manipulation here
              res.json(obj);
            } catch(e){
              console.log(e);
              res.status(500).json({ message: 'Something went wrong - parse error' });
            }
          });
      });
      request.end();
    
      request.on('error', (e) => {
        console.log(e);
        res.status(500).json({ message: 'Something went wrong - req error' });
      });
    });
    

    I added a JSON.parse() to show how you'd handle that if you wanted to do some manipulation of the data before sending it to the frontend. If you simply want to return the exact response of the coin API then use an end event like:

    response.on('end', () => {
      res.json(str);
    });