Search code examples
angularjsangular-http-interceptors

Angular - Limit HTTP interceptor retries


I've written an interceptor that, upon error of response, if the status code and an access token is present in local storage, retries the HTTP request.

I wrote this mostly to counter mysteriously failing responses from the API we're using (which I have no control of), because in some cases a retry sufficed. Sometimes the API endpoint would fail for no reason, so I figured that since I do not have control over the maintenance of the API I'd just retry sending the HTTP requests.

primesis.factory('httpResponseErrorInterceptor', function ($q, $injector) {
    return {
        'responseError': function (response) {
            if(response.status === 500 && localStorage.getItem('token')) {
                var $http = $injector.get('$http');
                return $http(response.config);
            }
            return $q.reject(response);
        }
    };
});

   $httpProvider.interceptors.push('httpResponseErrorInterceptor');

However, this results in an infinitely-retrying interceptor in those cases that there is indeed an error in the API.

What I'm trying to achieve is to put a limit in the retries of this interceptor. I've tried putting a counter in it but it seems like the counter does not carry on to the next interceptor call.

I've been searching for something that addresses a situation like this but to no avail. Is there a way to put limits on interceptor response error retries?


Solution

  • @csupnig's answer would work if you could picture it and write an implementation for it, but I managed to do it within the confines of the same interceptor itself: no added services.

    Here's how I did it:

    app.factory('httpResponseErrorInterceptor', function ($q, $injector) {
            return {
                responseError: function (response) {
                    if(response.status === 500 && localStorage.getItem('token')) {
                    var $http = $injector.get('$http');
    
                    if(response.config.Retries===undefined){
                        //do something on first error e.g, reporting
                        response.config.Retries=1;
                        return $http(response.config);
                    }else{
                        if(response.config.Retries!==2){
                            response.config.Retries = response.config.Retries +1;
                            return $http(response.config);
                        }
                        else{
                            response.config.Retries = undefined;
                            //do something on last retry
                            return $q.reject(response);
                        }
                    }
                }
                return $q.reject(response); // give up
            }
        };
    }); 
    

    This works by attaching the counter on the response config itself.

    I admit this could use some refactoring, but you get the idea. This worked for my use case, and I think this is fairly easy enough to alter.