This question already has answers here:
how to get data from response from fetch javascript request
(2 answers)
Closed 6 months ago.
I am trying to retrieve a response from an API using fetch in NextJS, I can get the message by calling the API but am unable to get anything using fetch. All I get from fetch is response 201 message that it's created.
When I run the API in postman I get the response:
{
"id": "21a1f0a6-f6c4-4aaf-9f48-2c9dba276646",
"status": "SUBMITTED"
}
But when I call the API using fetch in NestJS I get the response:
Response { type: "cors", url: "http://localhost:9000/api/v1/fireblocks/createTxnVaultToVault", redirected: false, status: 201, ok: true, statusText: "Created", headers: Headers, body: ReadableStream, bodyUsed: false }
Expected Behavior
The expected behavior is to get the same response as the API postman response. I need the tracking id to be passed into the UI
Backend - API Service & Controller Code in NestJS
Below is the API to run a transaction, it's coming from a NodeJS like framework (NestJS):
async createTxnVaultToVault(txn: Txn) {
this.logger.log("Creating transaction for account: " + txn);
this.logger.log("Transaction data: " + JSON.stringify(txn));
const payload: TransactionArguments = {
assetId: txn.asset,
source: {
type: PeerType.VAULT_ACCOUNT,
id: String(txn.source)
},
destination: {
type: PeerType.VAULT_ACCOUNT,
id: String(txn.dest)
},
amount: String(txn.amount),
fee: String(txn.fee),
note: txn.note
};
this.logger.log("TXN Payload data: " + JSON.stringify(payload));
return fireblocks().createTransaction(payload)
.then(res => res)
.then(res => {
console.log(res)
return res;
})
.catch(err => {
console.log(err);
return err;
});
}
Below is the controller to run a transactions, it's coming from a NodeJS like framework (NestJS):
#ApiTags('Fireblocks Transactions - Create Vault to Vault Transaction')
#Post('/createTxnVaultToVault')
async createTxnVaultToVault(
#Body() txn: Txn
): Promise<any> {
return this.appService.createTxnVaultToVault(txn)
.catch(e => {
this.logger.log(e);
return getError(e);
});
}
Frontend - Fetch Code in NextJS
export async function transferFunds(txn) {
const req_url = process.env.NEXT_PUBLIC_FIREBLOCKS_SERVER + "/createTxnVaultToVault";
console.log(txn);
return fetch(req_url, {
method: 'POST',
headers: {
Accept: "application/json",
"Content-Type": "application/json",
'Access-Control-Allow-Origin': '*'
},
body: JSON.stringify(txn)
})
.then(resp => {
console.log(resp);
})
.then(resp => {
console.log(resp);
return resp;
})
.catch(err => {
console.log(err);
});
}
It worked by changing how the UI received data. Below is how the API should be called:
Frontend - Fetch Code in NextJS
export async function transferFunds(txn) {
const req_url = process.env.NEXT_PUBLIC_FIREBLOCKS_SERVER + "/createTxnVaultToVault";
console.log(txn);
return fetch(req_url, {
method: 'POST',
headers: {
Accept: "application/json",
"Content-Type": "application/json",
'Access-Control-Allow-Origin': '*'
},
body: JSON.stringify(txn)
})
.then( async resp => {
//console.log(await resp.json())
return await resp.json();
})
.then(data => {
console.log(data);
return data;
//return data;
});
}
Related
I am using third party API. The way it works is:
I send post request then Token is returned in response.
Then i use that Token to check status. Afterwards, report is returned in response
In postman, i make both calls separately and it is working, but in Axios I have 1 async function and 2 await Promises.
Postman(NodeJs - Axios) looks like this:
For getting Token:
var data = JSON.stringify({
"security": {
"pLogin": "a",
"pPassword": "io"
},
"data": {
"pHead": "005",
"pCode": "00433",
"pLegal": 1,
"pClaimId": "z4LpXRWZKecSnL-FQtgD",
"pReportId": 8,
"pReportFormat": 1
}
});
var config = {
method: 'post',
url: 'http://10.22.50.10/report/',
headers: {
'Content-Type': 'application/json'
},
data : data
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
For getting Report with the token:
var data = JSON.stringify({
"data": {
"pHead": "005",
"pCode": "00433",
"pToken": "kgqjismxdrpjnjaqnlnbmovcsvnkarfd",
"pClaimId": "z4LpXRWZKecSnL-FQtgD",
"pReportFormat": 1
}
});
var config = {
method: 'post',
url: 'http://10.22.50.10/report/status',
headers: {
'Content-Type': 'application/json'
},
data : data
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
My async function with Axios:
/* 1. Searching for client in database (Full name is used, but can be changed)*/
const client = await client.findOne({
name: body.name,
family_name: body.family_name,
patronymic: body.patronymic
});
if (!client) {
return res.status(401).json({ message: "Client is not registered" });
}
/* 2. If client was found in database, make an API call */
let credit_report;
try{
credit_report = await axios.post(
'http://10.22.50.10/report',
{
security: {
pLogin: 'a',
pPassword: 'io',
},
data: {
pHead: "005",
pCode: "00433",
pLegal: 1,
pClaimId: client.claim_id,
pReportId: 8,
pReportFormat: 1
}
},
{
headers: {
'content-type': 'application/json'
}
}
);
}catch(err){
return res.status(400).json({errorMessage: err.message})
}
// await new Promise(resolve => setTimeout(resolve, 3000));
if(!credit_report.data.data.token) return res.status(400).json({message: credit_report.data});
const credit_report_status = await axios.post(
'http://10.22.50.10/report/status',
{
data: {
pHead: "005",
pCode: "00433",
pToken: credit_report.data.data.token,
pClaimId: client.claim_id,
pReportFormat: 1
}
},
{
headers: {
'content-type': 'application/json'
}
}
);
console.log(credit_report_status)
if(credit_report_status.data.data.result == '05000') return res.status(200).json({ message: 'Client fetched.', clientData64: credit_report_status.data.data.reportBase64});
else return res.status(400).json({message: credit_report_status.data})
When I am using Postman to check my module, it is saying Error 400 Bad Request
I'm trying to send expo push notification via firebase cloud functions, in order to send notifications from the web app to devices that have downloaded the mobile app.
When I send the request from Postman, it works just fine... i get the ok response and the notification shows up on my phone. But when I try to make the request from the web app, i get this in the functions log:
Function execution took 22 ms, finished with status: 'crash'
Any ideas why is this happening? Couldn't find anything to explain this so far.
Here's my function:
exports.reportNotification = functions.https.onRequest((request, response) => {
const tokens = request.body.expoPushToken;
let messages = [];
tokens.forEach((token) =>
messages.push({
to: token,
title: "title",
body: "message",
sound: "default",
_displayInForeground: "true",
})
);
fetch("https://exp.host/--/api/v2/push/send", {
method: "POST",
headers: {
Accept: "application/json",
"Accept-encoding": "gzip, deflate",
"Content-Type": "application/json",
},
body: JSON.stringify(messages),
})
.then((res) => response.status(200).json({ res: res }))
.catch((err) => response.status(400).json({ error: err }));
});
My post request on Postman:
{
"expoPushToken": ["ExponentPushToken[xxx-xxxxxxxxxxxxx]"]
}
And I call the function with axios in the web app:
axios({
url: "reportNotification",
baseURL: functionsBaseURL,
method: "post",
data: {
expoPushToken: tokens,
},
})
I checked and the tokens on this request are in the same format that the one on Postman.
Thanks.
It was a cors problem, solved with this modification:
exports.reportNotification = functions.https.onRequest((request, response) => {
cors(request, response, () => {
const tokens = request.body.expoPushToken;
let messages = [];
tokens.forEach((token) =>
messages.push({
to: token,
title: "title",
body: "message",
sound: "default",
_displayInForeground: "true",
})
);
axios.post("https://exp.host/--/api/v2/push/send", JSON.stringify(messages), {
headers: {
"Accept": "application/json",
"Accept-encoding": "gzip, deflate",
"Content-Type": "application/json",
},
})
.then((res) => response.status(200).json({ res: res }))
.catch((err) => response.status(200).json({ error: err }));
});
});
I am currently trying to work with the Atlassian Jira rest API. In order to not get a CORS error I go through the recommended route of not sending the request from the browser but proxy it through my express server.
Now as I am doing this, all I receive back in the app is a pending promise. I assume that I have not correctly resolved it at one point but I cant figure out where.
API Handler sending the request to the proxy:
const baseURL = `${apiConfig}/jiraproxy`;
export const testConnection = integration => {
return fetch(`${baseURL}/get`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify(integration)
})
.then(handleResponse)
.catch(handleError);
};
Jira Proxy Endpoint on the Express Server
const baseURL = `rest/api/3/dashboard`;
router.post("/get", (req, res) => {
fetch(req.body.link + baseURL, {
method: "GET",
headers: { Accept: "application/json" },
auth: {
username: req.body.credentials.username,
password: req.body.credentials.token
}
})
.then(handleResponse)
.catch(handleError);
});
handleResponse & handle Error Methods:
async function handleResponse(response) {
if (response.ok) {
return response.json();
}
if (response.status === 400) {
const error = await response.text();
throw new Error(error);
}
throw new Error("Network response was not ok.");
}
function handleError(error) {
// eslint-disable-next-line no-console
console.error(`API call failed. ${error}`);
throw error;
}
Goal:
Send the request of sending a request to the proxy and return the resonse of the proxy as the return of the initial "testConction" method.
Error:
No errors thrown, but the response received in the Browser is a pending promise.
Change to the Jira Proxy router fixed it. Thanks to #jfriend00.
router.post("/get", (req, res) => {
return fetch(req.body.link + baseURL, {
method: "GET",
headers: { Accept: "application/json" },
auth: {
username: req.body.credentials.username,
password: req.body.credentials.token
}
})
// This is the part that changed
.then(response => handleResponse(response))
.then(jiraResponse => res.status(200).json(jiraResponse))
.catch(handleError);
});
I have the following piece of code which is working perfect. However, my task is to replace fetch with axios. can you please guide, what would be the correct replacement of code in axios?
const create = async (credentials, software) => {
return await fetch('/api/software/create', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + credentials.t
},
credentials: 'include',
body: JSON.stringify(software)
})
.then((response) => {
return response.json()
}).catch((err) => console.log(err))
}
create({ t: jwt.token }, data)
.then((data) => {
if (data.error) {
this.setState({ error: data.error })
} else {
this.props.dispatch(initSoftware()); //if successful get the list of softwares in redux store
}
})
The data variable is an object which hold the req.body equivalent...
The above code is written in react and the create() is called within onSubmit eventhandler.
I am sure if I use axios the create() would be eliminated.. but how? Please guide..
It shouldn't be too different than what you currently have but something like this...
const create = async (credentials, software) => {
return await axios({
url: '/api/software/create'
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + credentials.t
},
withCredentials: true,
data: JSON.stringify(software)
})
.then((response) => {
return response.data;
}).catch((err) => console.log(err))
}
create({ t: jwt.token }, data)
.then((data) => {
if (data.error) {
this.setState({ error: data.error })
} else {
this.props.dispatch(initSoftware()); //if successful get the list of softwares in redux store
}
})
Note that the data you would be looking for should be in a property called data.
For more, check out the API references here.
2021 answer: just in case you land here looking for how to make GET and POST Fetch api requests using async/await or promises as compared to axios.
I'm using jsonplaceholder fake API to demonstrate:
Fetch api GET request using async/await:
const asyncGetCall = async () => {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
const data = await response.json();
// enter you logic when the fetch is successful
console.log(data);
} catch(error) {
// enter your logic for when there is an error (ex. error toast)
console.log(error)
}
}
asyncGetCall()
Fetch api POST request using async/await:
const asyncPostCall = async () => {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
// your expected POST request payload goes here
title: "My post title",
body: "My post content."
})
});
const data = await response.json();
// enter you logic when the fetch is successful
console.log(data);
} catch(error) {
// enter your logic for when there is an error (ex. error toast)
console.log(error)
}
}
asyncPostCall()
GET request using Promises:
fetch('https://jsonplaceholder.typicode.com/posts')
.then(res => res.json())
.then(data => {
// enter you logic when the fetch is successful
console.log(data)
})
.catch(error => {
// enter your logic for when there is an error (ex. error toast)
console.log(error)
})
POST request using Promises:
fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
// your expected POST request payload goes here
title: "My post title",
body: "My post content."
})
})
.then(res => res.json())
.then(data => {
// enter you logic when the fetch is successful
console.log(data)
})
.catch(error => {
// enter your logic for when there is an error (ex. error toast)
console.log(error)
})
GET request using Axios:
const axiosGetCall = async () => {
try {
const { data } = await axios.get('https://jsonplaceholder.typicode.com/posts')
// enter you logic when the fetch is successful
console.log(`data: `, data)
} catch (error) {
// enter your logic for when there is an error (ex. error toast)
console.log(`error: `, error)
}
}
axiosGetCall()
POST request using Axios:
const axiosPostCall = async () => {
try {
const { data } = await axios.post('https://jsonplaceholder.typicode.com/posts', {
// your expected POST request payload goes here
title: "My post title",
body: "My post content."
})
// enter you logic when the fetch is successful
console.log(`data: `, data)
} catch (error) {
// enter your logic for when there is an error (ex. error toast)
console.log(`error: `, error)
}
}
axiosPostCall()
I have 2 different axios POST calls. The first one makes use of the .post method and this successfully uploads the image to the database.
return axios
.post("http://localhost:3000/api/v1/upload", data, {
headers: {
"Content-Type": "multipart/form-data"
}
})
.then(response => {
console.log("The response", response);
})
.catch(error => {
console.log("Error", error);
});
However the method below does not seem to work properly and throws an error in the database / backend. But it does use the exact same configuration... :
Axios call that makes use of the Network utility function:
return httpPost(
process.env.NODE_ENV
? `https://tabbs-api.herokuapp.com/api/v1/upload`
: `http://localhost:3000/api/v1/upload`,
{
data
},
null
)
.then(response => {
console.log("uploaded", response);
})
.catch(error => {
console.log("Error", error);
});
Network Utility function:
export function httpPost(url, data, token) {
return axios({
method: "post",
url: url,
data: data,
headers: {
Authorization: "Bearer" + " " + token,
"Content-Type": "multipart/form-data"
}
});
}