I am trying to retrieve data from my own rest api. On the backend side I have express-rate-limit in use. Now I am trying to handle 429 error when it occurs. I want to display something to the user like "
Too many requests, please try again later.
How can I read the statusText of the error?
try {
const data = await fetch("http://localhost:5000/login", {
method: "POST",
body: JSON.stringify(
{
email
password
}
),
headers: {
"Accept": "application/json",
'Content-Type': 'application/json'
}
})
const result = await data.json()
if (data.status !== 200) {
throw new Error(result.detail.message)
}
console.log(result)
} catch (e) {
console.log(e) //shows: There was an error SyntaxError
}
Related
have a good time! I use axios to send a post request to the api http://freerealapi.com/ I work based on the document but it gives me an error 400 What should I do?
const buildDiscount = async token => {
let data = new FormData();
data.append('title', keyCodes);
data.append('text', 'test text');
data.append('image', file);
data.append('tags', 'one,two,three');
try {
const res = await axios.post('https://api.freerealapi.com/panel/blogs/', data, {
headers: {
'Content-Type': 'multipart/form-data',
Authorization: `Bearer ${token}`,
},
})
console.log(res.data);
} catch (error) {
console.log(error.response);
}
}
This function is most probably missing those 2 extra variables ( keyCodes, file ), can you provide those inputs to the function? That's probably the reason why the request is being malformed.
Background:
I'm trying the simple web push notifications example given in Google's documentation of the same (link: https://developers.google.com/web/fundamentals/push-notifications/subscribing-a-user)
I keep running into a SyntaxError: JSON.parse: unexpected character at line 2 column 1 of the JSON data error, which means I'm doing something fundamentally wrong. I'm a JS neophyte, can you help?
My simple function to subscribe user to push is simply:
function subscribeUserToPush() {
const pub_key = document.getElementById("notif_pub_key");
const service_worker_location = document.getElementById("sw_loc");
return navigator.serviceWorker.register(service_worker_location.value)
.then(function(registration) {
const subscribeOptions = {
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(pub_key.value)
};
return registration.pushManager.subscribe(subscribeOptions);
})
.then(function(pushSubscription) {
sendSubscriptionToBackEnd(pushSubscription);
return pushSubscription;
});
}
And sendSubscriptionToBackEnd() essentially uses fetch like so:
function sendSubscriptionToBackEnd(subscription) {
const sub_obj = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'CSRFToken':get_cookie('csrftoken')
},
body: JSON.stringify(subscription)
}
return fetch('/subscription/save/', sub_obj)
.then(function(response) {
if (!response.ok) {
throw new Error('Bad status code from server.');
}
return response.json();
})
.then(function(responseData) {
if (!(responseData.data && responseData.data.success)) {
throw new Error('Bad response from server.');
}
});
}
This fails with the error SyntaxError: JSON.parse: unexpected character at line 2 column 1 of the JSON data.
Doing console.log(sub_obj) shows this object:
Object { method: "POST", headers: {…}, body: "{\"endpoint\":\"https://updates.push.services.mozilla.com/wpush/v2/gAAAAABcaErG3Zn6Urzn5Hfhpyjl0eJg_IVtcgZI-sQr5KGE0WEWt9mKjYb7YXU60wgJtj9gYusApIJnObN0Vvm7oJFRXhbehxtSFxqHLOhSt9MvbIg0tQancpNAcSZ3fWA89E-W6hu0x4dqzqnxqP9KeQ42MYZnelO_IK7Ao1cWlJ41w8wZSlc\",\"keys\":{\"auth\":\"AJfXcUMO3ciEZL1DdD2AbA\",\"p256dh\":\"BN84oKD3-vFqlJnLU4IY7qgmPeSG96un-DttKZnSJhrFMWwLrH2j1a0tTB_QLoq5oLCAQql6hLDJ1W4hgnFQQUs\"}}" }
Also doing console.log(response); right before return response.json(); displays:
Response { type: "basic", url: "http://127.0.0.1:8001/subscription/save/", redirected: false, status: 200, ok: true, statusText: "OK", headers: Headers, body: ReadableStream, bodyUsed: false }
What's the problem and how do I fix it?
Changing return response.json() to return response.text() and then doing a console log on responseData gives the entire HTML of the page. I end up with the error Error: Bad response from server.
The main issue was that CSRFToken was mislabeled when being set in sendSubscriptionToBackEnd. It should have been X-CSRFToken. I.e.
function sendSubscriptionToBackEnd(subscription) {
const sub_obj = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken':get_cookie('csrftoken'),
},
body: JSON.stringify(subscription)
}
return fetch('/subscription/save/', sub_obj)
.then(function(response) {
console.log(response);
if (!response.ok) {
throw new Error('Bad status code from server.');
}
return response.json();
})
.then(function(responseData) {
// response from the server
console.log(responseData)
if (!(responseData.data && responseData.data.success)) {
throw new Error('Bad response from server.');
}
});
}
So why was this leading to return response.json(); failing?
Because the project in question routes requests that fail csrf checks to a default view - one which doesn't return a json response at all. Mystery solved!
I want to use received data from server on client . I use a NodeJS Server with NextJS and React.
I use this function on the server:
function addEmailToMailChimp(email, callback) {
var options = {
method: 'POST',
url: 'https://XXX.api.mailchimp.com/3.0/lists/XXX/members',
headers:
{
'Postman-Token': 'XXX',
'Cache-Control': 'no-cache',
Authorization: 'Basic XXX',
'Content-Type': 'application/json'
},
body: { email_address: email, status: 'subscribed' },
json: true
};
request(options, callback);
}
The function will be run from this point:
server.post('/', (req, res) => {
addEmailToMailChimp(req.body.email, (error, response, body) => {
// This is the callback function which is passed to `addEmailToMailChimp`
try {
var respObj = {}; //Initial response object
if (response.statusCode === 200) {
respObj = { success: `Subscribed using ${req.body.email}!`, message: JSON.parse(response.body) };
} else {
respObj = { error: `Error trying to subscribe ${req.body.email}. Please try again.`, message: JSON.parse(response.body) };
}
res.send(respObj);
} catch (err) {
var respErrorObj = { error: 'There was an error with your request', message: err.message };
res.send(respErrorObj);
}
});
})
The try method is used to verify that an email address could be successfully saved to MailChimp. An appropriate message is sent to the client.
On the Client-Side, i use this function to receive and display the data from the server:
handleSubmit() {
const email = this.state.email;
this.setState({email: ""});
fetch('/', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({email:email}),
}).then(res => {
if(res.data.success) {
//If the response from MailChimp is good...
toaster.success('Subscribed!', res.data.success);
this.setState({ email: '' });
} else {
//Handle the bad MailChimp response...
toaster.warning('Unable to subscribe!', res.data.error);
}
}).catch(error => {
//This catch block returns an error if Node API returns an error
toaster.danger('Error. Please try again later.', error.message);
});
}
The problem: The email address is saved successfully at MailChimp, but the message is always displayed: 'Error. Please try again later.'from the .catch area. When i log the error from the catch area i get this:
TypeError: Cannot read property 'success' of undefined
Where is my mistake? I have little experience in Node.js environments. I would be very grateful if you could show me concrete solutions. Thank you for your replies.
With fetch theres no data property on the response. You have to call res.json() and return that promise. From there the response body will be read and deserialized.
handleSubmit() {
const email = this.state.email;
this.setState({email: ""});
fetch('/', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({email:email}),
})
.then(res => {
console.log(res); //to make sure the expected object is returned
if(res.data.success) {
//If the response from MailChimp is good...
toaster.success('Subscribed!', res.data.success);
this.setState({ email: '' });
} else {
//Handle the bad MailChimp response...
toaster.warning('Unable to subscribe!', res.data.error);
}
}).catch(error => {
//This catch block returns an error if Node API returns an error
toaster.danger('Error. Please try again later.', error.message);
});
}
Two things you need to change:
Call and wait for res.json() to get the response body as json object.
The result of 1. is your 'data' object that you can use directly
handleSubmit() {
//...
fetch('/', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({email:email}),
})
.then(res => res.json())
.then(data => {
if(data.success) {
//...
toaster.success('Subscribed!', data.success);
} else {
toaster.warning('Unable to subscribe!', data.error);
}
}).catch(error => {
//...
});
}
First of all sorry for my English...
I have an asmx in C# that send data in json with an fetch API Call in the client side, i was using the jQuery.Ajax call before, but i want to start using fetch API.
This is how i do the Fetch Call.
I call the function fetchcall passing the url and if is needed the JS object with the parameters to be send by POST
const jdata = await fetchcall(url, "")
Then in my function i do this
async function fetchcall(url, data) {
const PostData = {
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=utf-8'
},
dataType: 'json'
//credentials: 'include'
}
if (data) { PostData.body = JSON.stringify(data) }
try {
const response = await fetch(url, PostData)
const json = await (handleErrors(response)).json();
//This is a temporary solution to the problem
if (json == 'Su sesion ha expirado favor de ir a pagina de login e iniciar session') {
alert(json);
return false;
}
return json
} catch (e) {
console.log(e)
}}
And this is the handleErrors function
function handleErrors(response) {
if (!response.ok) {
throw Error(response.statusText);
}
return response;
}
Right now i am testing the error without sending the credentials, so i get a error for the Session
And in my C# asmx i have this
[WebMethod(Description = "Load Countries", EnableSession = true)]
[System.Web.Script.Services.ScriptMethod(ResponseFormat = System.Web.Script.Services.ResponseFormat.Json)]
public string fillcbocountries()
{
var authCookie = Session["uid"];
if (authCookie == null)
throw new Exception("Your session has expired please go to login page and start session");}
With that the web services is throwing me an error with the message of Your session has expired please go to login page and start session
But wen i check the response of the fetch API in the handleError function i only get a statusText:"Internal Server Error" and i want the message that the server respond.
With jQuery.Ajax i do this
error: function (xhr, textStatus, error) {
var errorM = $.parseJSON(xhr.responseText);
console.log(errorM.Message)
}
And i get the
Your session has expired please go to login page and start session
Thank you for the help and regards
I discovered how to handle the error correctly if an exception is sent from C#
I removed the handleErrors function and check the response inside the fetchcall
so if the response.ok is false then i check the json data that the server respond and get the json.Message.
This is the end code
async function fetchcall(url, data) {
const PostData = {
method: 'POST',
headers: {
"Accept": "application/json",
'Content-Type': 'application/json; charset=utf-8'
},
dataType: 'json',
credentials: 'include'
}
if (data) { PostData.body = JSON.stringify(data) }
try {
//const url = 'services/common.asmx/fillcbopais'
const response = await fetch(url, PostData)
const jdata = await response.json();
if (!response.ok) {
alert(jdata.Message);
throw Error(jdata.Message)
}
return json
} catch (e) {
console.log(e)
}}
In case someone else has this problem I hope I can help
I'm trying to create a scheme to intercept and handle requests from an API middleware, however, for whatever reason I'm unable to properly handle non JSON responses from my API endpoint. The following snippet works just fine for server responses formatted in JSON however say an user has an invalid token, the server returns a simple Unauthorized Access response that I'm unable to handle even though I am supplying an error callback to the json() promise. The Unauthorized Access response message is lost in the following scheme.
const callAPI = () => { fetch('http://127.0.0.1:5000/auth/', {
method: 'GET',
headers: {
'credentials': 'include',
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Basic bXlKaGJHY2lPaUpJVXpJMU5pSXNJbVY0Y0NJNk1UUTVPRE15TVRNeU5pd2lhV0YwSWpveE5EazRNak0wT1RJMmZRLmV5SnBaQ0k2TVgwLllFdWdKNF9YM0NlWlcyR2l0SGtOZGdTNkpsRDhyRE9vZ2lkNGVvaVhiMEU6'
}
});
};
return callAPI().then(res => {
return res.json().then(responseJSON => {
if(responseJSON.status === 200){
return dispatch({
type: type[1],
data: responseJSON,
message: success
});
} else if(responseJSON.status === 401) {
return dispatch({
type: type[2],
message: responseJSON.message
});
}
return Promise.resolve(json);
}, (err) => {
console.log(err.toString(), ' an error occured');
});
}, err => {
console.log('An error occured. Please try again.');
});
Try using text method of Body: res.text().
Try to wrap your response handling code in a try...catch block like this:
return callAPI().then(res => {
try {
return res.json().then(responseJSON => {
[...]
catch(e) {
console.error(e);
}
});
Body.json() throws when the body is actually not JSON. Therefore, you should check if the body contains JSON before you call json() on it. See https://developer.mozilla.org/en-US/docs/Web/API/Response.