JS https request returning undefined Response - javascript

I am trying to make an API call from my JavaScript app to an endpoint in another application.
When I call the endpoint I get the status code and the message, but I cannot access the response body in any way. I have tried different ways to get the data, but nothing seems to work for me.
In the method "someAction", I want to use the data in the response/result from the API call. I added the outputs that the single log-lines print in the code.
How can "result" be undefined while "result.status/message" are defined?
What do I have to do in order to get the data/body as JSON or String?
The API itself is tested and returns data when tested in postman.
Thanks for your help!
const request = require('request')
let callEndpoint = () => {
return new Promise((resolve, reject) => {
const url = `https://my.api.com/endpoint`
const requestOptions = {
url: url,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
'My-API-Authorization': '123456789'
},
json: true,
strictSSL: false
}
request.get(requestOptions, (err, response) => {
if(err)
{
return reject(err);
}
return resolve(response);
});
});
}
let someAction = () => {
callEndpoint()
.then(result => {
logger.logInfo(result.statusCode) // => 200
logger.logInfo(result.statusMessage) // => OK
logger.logInfo(result) // => undefined
logger.logInfo(result.toString()) // => [object Object]
logger.logInfo(result.body) // => undefined
logger.logInfo(result.data) // => undefined
JSON.parse(result.toString()) // => Unexpected token o in JSON at position 1
JSON.parse(result) // => Unexpected token o in JSON at position 1
// DO SOME STUFF WITH THE RESULT
})
}

Related

Problem returning response from POST request with Axios in Node.js

I am writing a simple post request in a Firebase Cloud function, with Axios. This function calls an API endpoint and gets an object of profile details as response. My problem is to correctly return the response to the client.
In the code below, the Cloud Function logs the result correctly. But I can't figure out how to correctly return it to the client from the client-side callGetProfile() function. (Which runs inside a Vue3 method.)
I am probably missing something obvious but am very new to Node.js and HTPP requests.
Thanks for any help!
// MY FUNCTION IN NODE.JS (Firebase Cloud Functions)
exports.getProfile = functions.https.onCall((data, context) => {
var postData = {
profile_id: "xxxxxxxxxxxxxxxxx", //hardcoded here for testing but should be passed in "data" arg.
profile_type: "personal",
};
let axiosConfig = {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'X-API-KEY': 'XXXXXXXXXXXXXXXXXXXXXXXXXXXX'
}
};
axios.post('xxxxxxxxxxxxxxxxxxxxxxxxxxxxx', postData, axiosConfig)
.then((res) => {
console.log(res.data) // this works, I get all the data correctly!!
return res // also tried res.data
})
.catch((err) => {
console.log("AXIOS ERROR: ", err);
})
});
// MY FUNCTION CLIENT SIDE (Vue3 method)
const functions = getFunctions();
const callGetProfile() = httpsCallable(functions, "getProfile");
callGetProfile()
.then((result) => {
console.log(result.data) // this doesn't work, data is "null"
})
.catch((e) => console.log(e));

React/Javascript - TypeError: Cannot read properties of undefined (reading 'json')

React & Javascript noob here, I'm trying to build my first React project. What I want to do is to have a button that fetches automatically the last matches I played on a game. I'm using a API that, when called correctly, returns this json:
{data:
[{id: 0, internal_id: "_map_id_halo1_pillar_of_autumn", name: "The Pillar Of Autumn"},
…]}
I want to extract the name for each object of data and display an unordered list below the button.
But when I click the button, the browser displays the error:
TypeError: Cannot read properties of undefined (reading 'json')
The code that does what I mentioned is as follows:
async fetchHaloMaps()
{
const url = 'https://cryptum.halodotapi.com/games/hmcc/metadata/maps'
const mapNames = [];
fetch(url, {
"method": 'GET',
"headers": {
'Content-Type': 'application/json',
'Cryptum-API-Version': '2.3-alpha',
'Authorization': 'Cryptum-Token XXX'
}
})
.then(response => {
console.log(response);
if (!response.ok)
throw new Error("Response not ok!");
})
.then(response =>
response.json())
.then(data => {
const i=0;
for (const d of data)
{
mapNames[i] = d.name;
i++;
}
this.setState((state, props) => ({
numberOfMaps : i
}));
})
.catch(error => {
console.log("There was an error: " + error);
});
}
I think I'm "parsing" the JSON in the wrong way. But in the JSON, data i indeed an array with a "name" attribute. So I wanted to cycle the data array and copy the attribute "name", but the code above is not working.
I know the HTTP request with fetch does succeed, since in the console.log I can see the response object and it has the 200 OK field, and I can see the JSON associated with the browser developer tools.
You did not return anything from this .then:
.then(response => {
console.log(response);
if (!response.ok)
throw new Error("Response not ok!");
})
so there is no value that gets passed along to the next .then.
While you could do return response, a better approach would be to remove the intermediate .then entirely - only insert a .then when you need to wait for something asynchronous. At the time you get the response, you can check if it's OK and then return the .json(), without waiting in between.
.then(response => {
if (!response.ok) {
throw new Error("Response not ok!");
}
return response.json();
})
.then(data => {

Getting .json is not a function on Promise.all w/fetch

Oh once again I have those Promise.all blues:( I have a function that makes an array of fetch call's from provided urls and then we want to retrieve data via a Promise.all and return array of reponses or better yet just return the promise to calling function. . The problem is this results in error w/console showing:
There was problem retrieving data. TypeError: r.json is not a function
The code for the function is :
const getLeagueLeaders = (url, params) => {
// First let's create the array of url's
let queryURLs = [];
params.forEach((param) => {
queryURLs.push(
fetch(`${url}${new URLSearchParams(param)}`, {
method: "get",
headers: {
Authorization:
"Basic ==",
},
}).then((res) => res.json())
);
});
return (
Promise.all(queryURLs)
// map array of responses into an array of response.json() to read their content
.then((responses) => responses.map((r) => r.json()))
.catch((err) => {
console.error("There was problem retrieving data.", err);
})
);
};
module.exports = getLeagueLeaders;
And in Vue component
mounted: async function () {
const leagueLeadersResponseArray = await getLeagueLeaders(
this.fetchBaseUrl,
this.params
);
this.qbLeaders =
leagueLeadersResponseArray[0].cumulativeplayerstats.playerstatsentry;
Obviously leagueLeadersResponseArray is undefined. I researched .json() and dont see how I am using it incorrectly. At first i thought I needed a Promise.all wrapper for the responses.map((r) => r.json()) but that did no good either. I looked at this link but I am not using fetch as he is. Any guidance much appreciated....
Updated working code for anybody else:
// ---------- src/js/modules/ ------------------ //
/* jshint ignore:start */
// Make function to retrieve League Leaders in a Category
const getLeagueLeaders = (url, params) => {
// First let's create the array of url's
let queryURLs = [];
params.forEach((param) => {
queryURLs.push(
fetch(`${url}${new URLSearchParams(param)}`, {
method: "get",
headers: {
Authorization:
"Basic ==",
},
}).then((res) => res.json())
);
});
return Promise.all(queryURLs).catch((err) => {
console.error("There was problem retrieving data.", err);
});
};
module.exports = getLeagueLeaders;
Your template string is around the entire fetch when it should only be in the argument to fetch:
params.forEach((param) => {
queryURLs.push(fetch(`${url}${new URLSearchParams(param)}`, {
method: "get",
headers: {
Authorization:
"Basic *****==",
}
}));
});
Then, you have a .then(data => {return data}), which doesn't do anything since the return returns from the then callback, not the function. You should instead return the promise that Promise.all gives you:
return Promise.all(queryURLs)
// map array of responses into an array of response.json() to read their content
.then((responses) => responses.map((r) => r.json())) // Get error There was problem retrieving data. TypeError: r.json is not a function
.catch((err) => {
console.error("There was problem retrieving data.", err);
});

How can I convert this fetch post request into an axios post request?

Currently I am trying to convert a working fetch POST request into an Axios POST request. However, I keep getting this Error -> 'Uncaught (in promise) Error: Request failed with status code 400'.
This is my working fetch request code below:
async function postData(url ='', data = { }) {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json' },
body: JSON.stringify(data) });
let txoData = await response.json();
let a = txoData.payload.substring(68,134);
console.log(a);
console.log(txoData)
}
postData('https://merchantapi.taal.com/mapi/tx', { 'rawtx': rawtx })
.then(txoData => { return txoData })
.then(a => { return a })
and this is my NOT working convert to Axios attempt below:
async function postData() {
const response = await axios.post('https://merchantapi.taal.com/mapi/tx', {'rawtx': rawtx});
let txoData = await response.json();
let a = txoData.payload.substring(68,134);
console.log(a);
console.log(txoData)
}
postData()
.then(txoData => { return txoData })
.then(a => { return a })
I would greatly appreciate any help on this issue :)) x
To pass custom headers while using axios supply an object containing the headers as the last argument

GET Request 200 to json

I am trying to send a fetch request to a URL to receive some JSON, all I get back is HTTP/1.1 200 OK, when I try to console.log my request, I don't see anything in the console, I am trying to console.log the request as JSON. I am using Cloudflare's wrangler tool for the project and coding it in javascript Here is my code:
addEventListener('fetch', event => {
event.respondWith(handleRequest((event)))
})
/**
* Respond with hello worker text
* #param {Request} request
*/
async function handleRequest(request) {
return new Response('Hello worker!', {
headers: { 'content-type': 'application/json' },
})
}
const url =`URL`;
const res="";
fetch(`MYURL`)
.then((response) => {
return response.json();
})
.then((data) => {
dataRecieved=JSON.parse(data);
console.log(dataRecieved);
});
'Hello worker!' is not a valid JSON so JSON.parse(data) will not be able to work properly. You should use a code like this to return a valid JSON in the response:
return new Response('{"variants":["your-private-url/variants/1","your-private-url/variants/2"]}', {
headers: { 'content-type': 'application/json' },
status: 200
})
Now to have the result as you mentioned in your comments you need to remove the event listener and handle the fetch call this way:
fetch('your-private-url')
.then((response) => {
return response.json();
})
.then((data) => {
// 'data' here contains the object returned by your request.
// So you can log the whole object received to see its content:
console.log('Received data:\n', data);
// And you can access the fields and log them:
data.variants.forEach(variant => {
console.log('Reveived variant: ', variant);
});
});

Categories