The API my webapp is talking to sometimes overloads and is sending 500 Internal Server Error if it cannot handle request.
There are 100+ different requests my web applic
You can check for any possible server side errors by expanding the status code check a little more. This interceptor will attempt to retry the request multiple times and will do so on any response code 500 or higher. It will wait 1 second before retrying, and give up after 3 tries.
$httpProvider.interceptors.push(function ($q, $injector) {
var retries = 0,
waitBetweenErrors = 1000,
maxRetries = 3;
function onResponseError(httpConfig) {
var $http = $injector.get('$http');
setTimeout(function () {
return $http(httpConfig);
}, waitBetweenErrors);
}
return {
responseError: function (response) {
if (response.status >= 500 && retries < maxRetries) {
retries++;
return onResponseError(response.config);
}
retries = 0;
return $q.reject(response);
}
};
});
Angular provides reference to the config object which was used by $http service for doing the request in the response (response.config). That means if we can inject $http service in the interceptor we can easily resend the request. Simple injecting of $http service in the interceptor is not possible because of the circular dependency but luckily there is a workaround for that.
This is an example how the implementation of a such interceptor can be done.
$httpProvider.interceptors.push(function ($q, $injector) {
var incrementalTimeout = 1000;
function retryRequest (httpConfig) {
var $timeout = $injector.get('$timeout');
var thisTimeout = incrementalTimeout;
incrementalTimeout *= 2;
return $timeout(function() {
var $http = $injector.get('$http');
return $http(httpConfig);
}, thisTimeout);
};
return {
responseError: function (response) {
if (response.status === 500) {
if (incrementalTimeout < 5000) {
return retryRequest(response.config);
}
else {
alert('The remote server seems to be busy at the moment. Please try again in 5 minutes');
}
}
else {
incrementalTimeout = 1000;
}
return $q.reject(response);
}
};
});
Note: In this example implementation the interceptor will retry the request until you receive a response with status that is different than 500. Improvement to this can be adding some timeout before retrying and retrying only once.
I wanted to retry requests in my response
block also, so combining multiple answers from different posts from SO, I've written my interceptor as follows -
app.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push(['$rootScope', '$cookies', '$q', '$injector', function ($rootScope, $cookies, $q, $injector) {
var retries = 0, maxRetries = 3;
return {
request: function (config) {
var csrf = $cookies.get("CSRF-Token");
config.headers['X-CSRF-Token'] = csrf;
if (config.data) config.data['CSRF-Token'] = csrf;
return config;
},
response: function (r) {
if (r.data.rCode == "000") {
$rootScope.serviceError = true;
if (retries < maxRetries) {
retries++;
var $http = $injector.get('$http');
return $http(r.config);
} else {
console.log('The remote server seems to be busy at the moment. Please try again in 5 minutes');
}
}
return r;
},
responseError: function (r) {
if (r.status === 500) {
if (retries < maxRetries) {
retries++;
var $http = $injector.get('$http');
return $http(r.config);
} else {
console.log('The remote server seems to be busy at the moment. Please try again in 5 minutes');
}
}
retries = 0;
return $q.reject(r);
}
}
}]);
}])
credits to @S.Klechkovski, @Cameron & https://stackoverflow.com/a/20915196/5729813