Handle Status 304 response with AngularJS $http - javascript

If i have one API server then the API is send ajax data with JSON format :
{"status":304,"message":"Cannot delete data where PK is empty or > 1"}
how to AngularJS $http post call the status and message to alert bootbox?
here my AngularJS $http post
$http({
method: "POST",
url: apiUrl('disable_assethw'),
data: {
id: id
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).then(function successCallback(response) {
if(response.status == 304) {
bootbox.alert("Something went error.." + response.data.message);
} else {
$scope.getAssetHW();
}
}, function errorCallback(response) {
bootbox.alert("Something went error.." + response.status);
});
thanks for advise.

When doing a POST request with JavaScript objects as data, use the AngularJS default content type (which is automatically set to application/json). The $http service also automatically encodes JavaScript objects as JSON strings.
Only response with status in the range 200-299 are processed by the success handler. Status outside the range are processed by the rejection handler:
$http({
method: "POST",
url: apiUrl('disable_assethw'),
data: {
id: id
},
headers: {
̶'̶C̶o̶n̶t̶e̶n̶t̶-̶T̶y̶p̶e̶'̶:̶ ̶'̶a̶p̶p̶l̶i̶c̶a̶t̶i̶o̶n̶/̶x̶-̶w̶w̶w̶-̶f̶o̶r̶m̶-̶u̶r̶l̶e̶n̶c̶o̶d̶e̶d̶'̶
}
}).then(function successCallback(response) {
̶i̶f̶(̶r̶e̶s̶p̶o̶n̶s̶e̶.̶s̶t̶a̶t̶u̶s̶ ̶=̶=̶ ̶3̶0̶4̶)̶ ̶{̶
̶b̶o̶o̶t̶b̶o̶x̶.̶a̶l̶e̶r̶t̶(̶"̶S̶o̶m̶e̶t̶h̶i̶n̶g̶ ̶w̶e̶n̶t̶ ̶e̶r̶r̶o̶r̶.̶.̶"̶ ̶+̶ ̶r̶e̶s̶p̶o̶n̶s̶e̶.̶d̶a̶t̶a̶.̶m̶e̶s̶s̶a̶g̶e̶)̶;̶
̶}̶ ̶e̶l̶s̶e̶ ̶{̶
$scope.getAssetHW();
̶}̶
}, function errorCallback(response) {
//HANDLE 304 status HERE
if(response.status == 304) {
bootbox.alert("Something went error.." + response.data.message);
} else {
bootbox.alert("Something went error.." + response.status);
};
});
From the Docs:
A response status code between 200 and 299 is considered a success status and will result in the success callback being called. Any response status code outside of that range is considered an error status and will result in the error callback being called. Also, status codes less than -1 are normalized to zero. -1 usually means the request was aborted.
— AngularJS $http Service API Reference
Note: A status of -1 usually indicates the browser rejected the request with a CORS problem that violates same-origin policy.

you said it is json response and you used: application/x-www-form-urlencoded , which is wrong.
The best practice to handle rest/api call is:
Create 1 common/general function which is accessible in whole application which will manage your post api call(add api response to callback):
postAPICall(url, body, data) {
let headers = new Headers({'Content-Type': 'application/json'});
this.http
.post(url,
body, {
headers: headers
})
.map(
response => response.json())
.subscribe(
response => {
data(response);
},
err => data(this.handleError(err)); //handle error here
);
}
call this function wherever required(in component or service):
var yourJSONBody = {
"param-1": "",
"param-2": "",
//....
}
}
this.myCommonService.postAPICall("localhost:8080/app/", yourJSONBody, data => {
if (data.status == "304") {
//do stuff
//this.msgs.push({severity: 'error', detail: data.message});
}
else {
//do stuff
}
});
error handler function:
private handleError(error: any) {
let description = 'There was an error: ' + error.status;
let errors = {
errorcode: error.status,
errorstatus: error.statusText,
errordescription: description
};
return errors;
}

Related

Trying to access error response 500 axios

I am not able to access the response of error - 500 in axios
export const dowloadFilePDF = (data) => {
return axios
.request({
method: 'GET',
url: `${basePath + data[0]}`,
responseType: 'blob',
headers: { Authorization: Authorization },
})
.then(response => {
console.log(response)
let fileName = response.headers['content-disposition']?.split(';')[1]?.split('=')[1]?.split('"').join('')
fileName = fileName ? fileName : 'data.pdf'
fileDownload(response.data, fileName)
})
.catch((error) => {
console.log(error.response.data)
})
}
I am not getting the response instead its returning as
data : Blob {size: 215, type: 'application/json'}
According to the documentation, you can't assume error.response will be filled in. Here's the code the documentation shows with the inline comments explaining it:
Handling Errors
axios.get('/user/12345')
.catch(function (error) {
if (error.response) {
// The request was made and the server responded with a status code
// that falls out of the range of 2xx
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
// The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
// http.ClientRequest in node.js
console.log(error.request);
} else {
// Something happened in setting up the request that triggered an Error
console.log('Error', error.message);
}
console.log(error.config);
});
There's another aspect to this as well: You're calling catch on the promise returned by then, not on the promise returned by axios. If the axios promise is rejected, you'll reach that rejection handler, but you'll also reach it if the axios promise is fulfilled but then your fulfillment handler throws an error (or returns a promise it ultimately rejects). In that latter case, the error probably won't have a response property at all.
the best way to catch errors instead of trying a lot of lines of code in the catch method by promise is using the tools in the Axios names interceptor.
interceptor has two property request and response. In response we can simulate the errors status and based on the status code we can do whatever we want. for example :
axios.interceptors.response.use(null, error => {
console.log("error : " , error);
const expectedError = error.response && error.response.status >= 400 &&
error.response.status < 500;
if (expectedError) {
return Promise.reject(error);
}
alert("unexpected error is happen");
});
if you need more help here is the original link

Interceptor for fetch and fetch retry? (Javascript)

I am trying to create an interceptor for fetch in javascript (React to be more specific). It should get the result from every fetch that gets called, and if it is an 401 error it should initiate a new fetch call to another route to get a cookie (a refresh token). Then, the original fetch call should be tried again (because now the user is logged in).
I have managed to trigger the new fetch call and send back the cookie for each, but I got these two problems below:
I do not now how to retry the fetch call after the refresh token has been recieved. Is that possible? I found the fetch-retry npm (https://www.npmjs.com/package/fetch-retry) but not sure how and if I can implement that on an interceptor when it should be done for the original fetch call.
I seem to be doing something wrong with async await (I think), because the intercept is not waiting for the fetch call before returning the data (the statuscode on the original fetch seems to be 401 and not 200 which it should be after we get the cookie. I also tried to return the response of the fetch inside the interceptor but that returned undefined).
Any idea about how to solve this? Anyone who have done something similar?
Below is my code:
(function () {
const originalFetch = fetch;
fetch = function() {
return originalFetch.apply(this, arguments).then(function(data) {
if(data.status === 401) {
console.log('not authorized, trying to get refresh cookie..')
const fetchIt = async () => {
let response = await fetch(`/api/token`, {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/json'
},
});
}
fetchIt();
}
return data
});
};
})();
EDIT: To make it more clear what I am after. I need an interceptor like I described above to work so I don't have to do something like this after every fetch call:
getData() {
const getDataAsync = async () => {
let response = await fetch(`/api/loadData`, { method: 'POST' });
if(response.status === 401) {
let responseT = await fetch(`/api/token`, {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/json'
},
});
if(responseT.status === 401) {
return responseT.status
}
if(responseT.status === 200) {
response = await fetch(`/api/loadData`, { method: 'POST' });
}
}
let data = await response.json();
//Do things with data
};
getDataAsync();
};
So basically the interceptor should:
Check if there is a 401, if so then:
fetch api/token
If api/token returns 401, it should just return that.
If api/token returns 200, it should run original fetch again
You can simple use originalFetch for token and await for response if response is 401 then you simply return empty response to first fetch call else you updated token and then let it go to next condition which will rerun old request.
let TEMP_API = {
'401': {
url: 'https://run.mocky.io/v3/7a98985c-1e59-4bfb-87dd-117307b6196c',
args: {}
},
'200': {
url: 'https://jsonplaceholder.typicode.com/todos/2',
args: {}
},
'404': {
url: 'https://jsonplaceholder.typicode.com/todos/1',
args: {
method: "POST",
credentials: "include"
}
}
}
const originalFetch = fetch;
fetch = function() {
let self = this;
let args = arguments;
return originalFetch.apply(self, args).then(async function(data) {
if (data.status === 200) console.log("---------Status 200----------");
if (data.status === 401) {
// request for token with original fetch if status is 401
console.log('failed');
let response = await originalFetch(TEMP_API['200'].url, TEMP_API['200'].args);
// if status is 401 from token api return empty response to close recursion
console.log("==========401 UnAuthorize.=============");
console.log(response);
if (response.status === 401) {
return {};
}
// else set token
// recall old fetch
// here i used 200 because 401 or 404 old response will cause it to rerun
// return fetch(...args); <- change to this for real scenarios
// return fetch(args[0], args[1]); <- or to this for real sceaerios
return fetch(TEMP_API['200'].url, TEMP_API['200'].args);
}
// condition will be tested again after 401 condition and will be ran with old args
if (data.status === 404) {
console.log("==========404 Not Found.=============");
// here i used 200 because 401 or 404 old response will cause it to rerun
// return fetch(...args); <- change to this for real scenarios
// return fetch(args[0], args[1]); <- or to this for real scenarios
return fetch(TEMP_API['200'].url, TEMP_API['200'].args);
sceaerios
} else {
return data;
}
});
};
(async function() {
console.log("==========Example1=============");
let example1 = await fetch(TEMP_API['404'].url, TEMP_API['404'].args);
console.log(example1);
console.log("==========Example2=============");
let example2 = await fetch(TEMP_API['200'].url, TEMP_API['200'].args);
console.log(example2);
console.log("==========Example3=============");
let example3 = await fetch(TEMP_API['401'].url, TEMP_API['401'].args);
console.log(example3);
})();
Example1 request made to api for 404 status which will cause the 404 condition to run which will then call 200 api after which response will be returned
Example2 request made to 200 api which will return 200 status code which will cause 200 condition to pass and run and return response
Example3 request made to api for 401 status which will cause 401 condition to pass which will then call 200 api and print response after which it will fall out of condition where you can set token which will then be used in another fetch request
Try retuning the fetch promise instead of awaiting that.
(function () {
const originalFetch = fetch;
fetch = function () {
return originalFetch.apply(this, arguments).then(function (data) {
if (data.status === 200) console.log("---------Status 200----------");
if (data.status === 404) {
console.log("==========404 Not Found.=============");
return fetch(`https://jsonplaceholder.typicode.com/todos/2`);
} else {
return data;
}
});
};
})();
function test(id) {
//will trigger 404 status
return fetch(`https://jsonplaceholder.typicode.com/todos/` + id, {
method: "POST",
credentials: "include",
});
}
test(1).then((i) => console.log(i));
Interceptor library for the native fetch command. It patches the global fetch method and allows you the usage in Browser, Node and Webworker environments.
fetch-retry It wraps any Fetch API package (eg: isomorphic-fetch, cross-fetch, isomorphic-unfetch and etc.) and retries requests that fail due to network issues. It can also be configured to retry requests on specific HTTP status codes.

Azure Function axios POST empty Response

I am trying to make an axios call in my React frontend to get some information from the backend to access some information. When I log the response on the server, I see the required information, but in the axios call, I get data = "" for some reason.
ReactJS Axios call
await axios
.post(url, {
token: this.props.authUser.idToken.rawIdToken,
blob_path: blobPath,
container: container
},
config
)
.then((response) => {
if(response.data == ""){
console.log("nada");
debugger;
}
callback(response);
})
.catch((error) => {
debugger;
callback(error);
});
Azure Server Response Code
exit = (result) => {
console.log("---------- RESULT ------------");
console.log(result);
console.log("------ END RESULT ------------");
context.res = {
status: 200 /* Defaults to 200 */,
body: result,
headers: { 'Content-Type': 'application/json' },
};
context.done();
};
The response on the backend
The response on the frontend
EDIT: Axios is sending double requests and the old request's response gets ignored.

Not getting http error codes from rest calls

I need to be able to differentiate between a 400 and 500 range error code for different flows in our application.
Lets say I have 3 rest calls,
First will return 200,
second will return 401,
and third will return 502
I started using aurelia-http-client, which is where I first noticed that I was getting the http error code = 0 in the promise`s reject callback.
Update: Using aurelia-fetch-client returns only a string as a error response, thus wasn't an option either.
I then tried using an ajax call and a basicXMLHttpRequest, which yielded the same result. For 200 range, I got the codes, but anything above, I received a statusCode of 0.
Update: I am running Version 63.0.3239.132 of Chrome if it makes a difference.
What I've tried:
I've tried about 5 different variations for fetch.
fetch(url, {
method: requestMessage.method,
headers,
body: JSON.stringify(content)
})
.then((result) => {
resolve(result)
})
.catch((error) => {
reject(error);
});
Outputs a string error
Using aurelia-http-client
this.httpClient.createRequest(url)
.asPut()
.withContent(params)
.send()
.then((response) => {
resolve(response);
},
(error) => {
reject(error);
});
- StatusCode is always 0 for errors
Also (This just builds up a dynamic XmlHttpRequest):
private retryRequest(): void {
var xhr = this.setupXhr();
xhr.onreadystatechange = () => this.stateChange(xhr);
setTimeout(() => {
xhr.send(JSON.stringify(this.content));
}, 1000);
}
private setupXhr(): XMLHttpRequest {
var xhr = new XMLHttpRequest();
xhr.open(this.method, this.url, true);
xhr = this.addHeaders(xhr);
return xhr;
}
private addHeaders(xhr: XMLHttpRequest): XMLHttpRequest {
for (let key in this.headers) {
if (this.headers.hasOwnProperty(key)) {
xhr.setRequestHeader(this.headers[key].key, this.headers[key].value);
}
}
return xhr;
}
private stateChange(xhr: XMLHttpRequest): void {
logger.debug(' ::>> xhr = ', xhr);
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 400) {
this.resolve(JSON.parse(xhr.response));
} else if (xhr.status >= 500) {
this.retryRequest();
} else {
// this.retryRequest();
this.reject(xhr.response); // call after a # of fails for this ???
}
}
}
Which only returns the 200 range http status codes
Also:
$.ajax({
type: requestMessage.method,
url,
data: JSON.stringify(content),
headers,
success: (data) => {
logger.debug(' ::>> rest call was a success ', data);
resolve(data);
},
statusCode: {
502: (jqXHR) => {
logger.debug(' ::>> received 502 ');
var retryAfter = jqXHR.getResponseHeader('Retry-After');
retryAfter = parseInt(retryAfter, 10);
if (!retryAfter) { retryAfter = 5 };
setTimeout(query, retryAfter * 1000);
}
}
});
- Which never gets to the 502 callback. I've tried other status codes as well
Is there a way of getting the error codes which I might be missing? Any help appreciated
I had similar requirement and have implemented this using following code
$.ajax({
type: "POST",
url: urlAjax,
dataType: 'json',
headers: headerValue,
data: _dataValue,
crossDomain: true,
beforeSend: function () {
//any operation
},
complete: function () {
// any after operation
},
success: function (data) {
// All 2XX will reach here
},
error: function (jqXHR, textStatus, error) {
var Check = JSON.parse(jqXHR['responseText']);
// In above array you will get whole error response
}
}).done(function (rs, textStatus, xhr) {
// on finished
});
In jqXHR, textstatus and errror params you will receive all the information about errors and codes related to it.
Hope that helps.
Found the issue:
I initially thought Harshal Bulsara's was what resolved my issue. It is a nice implementation, but I found the actual issue.
I found that our nginx response didn't send the required headers.
By adding the Access-Control-Allow-Origin header, I received the statusCode.

How to call a function only after getting response from restcall node js

I have one request.post call and another function.Where I need to pass the response of restcall as paramaters to the function.
The current issue which Iam facing here is that the function is getting called even before i get response from the rest call and null values are getting passed.I know that we need to use some callabcks for this issue.But I dont know how to do it.can someone help.
app.post('/verifycreds',function(req,res) {
var reqdata = req.body;
var data = {};
data.custid = reqdata.custid;
request.post({
url:'https://database.mybluemix.net/verifycredentials',
headers:{
'Content-Type':'application/json'
},
body:data,
json:true
}, function(err,response) {
verifycreds(response.body);
});
function verifycreds(data) {
if((datareq.customerid === data.customerid ) && (datareq.password == data.password)){
res.send("valid");
} else {
res.send("invalid");
}
}
So how can I call verifycreds function only after I get response from the request .post call..Any help!
Your callback is valid, the problem in callback parameters. It should be defined with three parameters:
error
response
body
So correct code is:
request.post({
url: 'https://database.mybluemix.net/verifycredentials',
headers: {
'Content-Type': 'application/json'
},
body: data,
json: true
}, function(err, res, body) {
// TODO: process possible errors
// if (err) { ...
verifycreds(body);
});

Categories

Resources