2

I'm trying to make a simple API that calls another API that will return some information. The thing is, in order to connect to the second API, I need to attach query parameters to it.

So what I've tried to do so far is to use an axios.get in order to fetch the API. If I didn't need to add queries on top of that, then this would be really simple but I'm having a really hard time trying to figure out how to attach queries on top of my request.

I've created an object that pulled the original query from my end and then I used JSON.stringify in order to turn the object I made into a JSON. Then, from my understanding of Axios, you can attach params my separating the URL with a comma.

On line 6, I wasn't sure if variables would carry over but I definitely can't have the tag var turned into the string "tag", so that's why I left it with the curly brackets and the back ticks. If that's wrong, then please correct me as to how to do it properly.

the var tag is the name of the query that I extracted from my end. That tag is what needs to be transferred over to the Axios GET request.

app.get('/api/posts', async (req, res) => {
    try {
        const url = 'https://myurl.com/blah/blah';
        let tag = req.query.tag;
        objParam = {
            tag: `${tag}`
        };

        jsonParam = JSON.stringify(objParam);

        let response = await axios.get(url, jsonParam);

        res.json(response);
    } catch (err) {
        res.send(err);
    }
});

response is SUPPOSED to equal a JSON file that I'm making the request to.

What I'm actually getting is a Error 400, which makes me think that somehow, the URL that Axios is getting along with the params aren't lining up. (Is there a way to check where the Axios request is going to? If I could see what the actual url that axios is firing off too, then it could help me fix my problem)

Ideally, this is the flow that I want to achieve. Something is wrong with it but I'm not quite sure where the error is.

-> I make a request to MY api, using the query "science" for example

-> Through my API, Axios makes a GET request to: https://myurl.com/blah/blah?tag=science

-> I get a response with the JSON from the GET request

-> my API displays the JSON file

Erik Philips
  • 53,428
  • 11
  • 128
  • 150
leed38
  • 314
  • 1
  • 4
  • 14
  • Why are you using string interpolation like this: ``{ tag: `${tag}` }``, when you could just do `{ tag: tag }`, or even just `{ tag }`? – kshetline Jul 21 '19 at 03:52
  • you might have better luck passing objParam (not stringified) as the second parameter. Or you might want to try using the stringify method from qs instead of using the one from JSON. I have found both helpful in axios – Jeremy Kahan Jul 21 '19 at 04:06
  • @kshetline I just wasn't sure if the value of an object would be valid without quotation marks. – leed38 Jul 21 '19 at 04:12

1 Answers1

3

After looking at Axios' README, it looks like the second argument needs the key params. You can try:

app.get('/api/posts', async (req, res, next) => {
    try {
        const url = 'https://myurl.com/blah/blah';
        const options = {
            params: { tag: req.query.tag }
        };

        const response = await axios.get(url, options);
        res.json(response.data);
    } catch (err) {
        // Be sure to call next() if you aren't handling the error.
        next(err);
    }
});

If the above method does not work, you can look into query-string.

const querystring = require('query-string');

app.get('/api/posts', async (req, res, next) => {
    try {
        const url = 'https://myurl.com/blah/blah?' +
            querystring.stringify({ tag: req.params.tag });

        const response = await axios.get(url);
        res.json(response.data);
    } catch (err) {
        next(err);
    }
});

Responding to your comment, yes, you can combine multiple Axios responses. For example, if I am expecting an object literal to be my response.data, I can do:

const response1 = await axios.get(url1)
const response2 = await axios.get(url2)
const response3 = await axios.get(url3)

const combined = [
    { ...response1.data },
    { ...response2.data },
    { ...response3.data }
]
khan
  • 1,466
  • 8
  • 19
  • I'm getting a typeerror: 'converting circular structure to JSON'. I tried using the JSON.stringify() on options before but I'm still getting the same error. – leed38 Jul 21 '19 at 04:04
  • 1
    You can possibly get around this error by doing `res.json(response.data)`. You can look [here](https://stackoverflow.com/questions/11616630/how-can-i-print-a-circular-structure-in-a-json-like-format) if you need other parts of the response. – khan Jul 21 '19 at 04:15
  • Hey, the response.data worked! Thank you so much for that. Do you think you can explain how / why that worked? What does 'converting circular structure to JSON' mean? – leed38 Jul 21 '19 at 04:29
  • You can receive the data from a successful Axios response through the `data` key. This is true for all methods that return data. Unfortunately, I do not know too much about the circular structure error, but I believe that Express is most likely using `JSON.stringify` under the hood for `res.json`. As quoted from this [site](https://makandracards.com/makandra/28847-dealing-with-typeerror-converting-circular-structure-to-json-on-javascript), *`JSON.stringify` can't serialize JavaScript structures that include circular references.* – khan Jul 21 '19 at 05:03
  • Then if I were to make multiple API calls, would I be able to use the ```data``` key in order to combine multiple API calls to show under one page? Like if I were to make three separate calls, would I be able to combine the information recieved if I turned the response from Axios into data? I'm not sure if my question makes sense tbh but ya.. haha – leed38 Jul 21 '19 at 05:24
  • 1
    I updated my post to answer your question. Answering it here, yes, you can use Axios' `response.data` as a JS plain object and combine them if needed. If you need to make multiple Axios calls, you can also consider using `axios.all()` with `axios.spread()`. – khan Jul 21 '19 at 05:52