Circular dependency while pushing http interceptor

3k views Asked by At

I am using http Interceptor to intercept each http request in my application. But I am getting Circular dependency found: $http <- APIInterceptor <- $http <- $templateRequest <- $compile

here is my Service code:

mPosServices.factory('mosServiceFactory', function ($http, $rootScope, $cookies, $q) {
    return{
         refresh_token: function () {
            var refreshToken = $http({
                method: "get",
                url: "myservice/oauth/token?grant_type=refresh_token&client_id=restapp&client_secret=restapp&refresh_token=" + $cookies.get('refresh_token'),
            })
            return refreshToken;
        }
});

mPosServices.service('APIInterceptor', ['mosServiceFactory','$cookies',function (mosServiceFactory,$cookies) {
        var service = this;
        service.request = function (config) {
            if (!$cookies.get('access_token')) { //if access_token cookie does not exist
               mosServiceFactory.refresh_token().then(function (response) {
                    var date = new Date();
                    date.setTime(date.getTime() + (response.data.expiresIn * 1000));
                    $cookies.remove('access_token');
                    $cookies.put('access_token', response.data.value, {expires: date});
                    $cookies.put('refresh_token', response.data.refreshToken.value);
                }); //call the refresh_token function first
            }
            return config;
        };

        service.responseError = function (response) {
            return response;
        };
    }]);

and pushing it as:

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

in config function. Am I doing something wrong here? Even I tried to inject $http manually using

$injector

, but getting same error. Kindly Help me.

1

There are 1 answers

4
dfsq On BEST ANSWER

You indeed need to add use $injector to get mosServiceFactory instance inside of interceptor. But this is not all you need to do. You also need to make sure you don't fall into infinite request loop because interceptor also makes a request. What you can do is to check if current request is the one for token refresh and if so don't fire one more request, I'm checking the URL for this.

One more important thing to mention. You need to return promise object from interceptor which resolves to original request config. This way it guaranties that intercepted request will be reissued after token is retrieved.

All together will look like this:

mPosServices.service('APIInterceptor', ['$injector', '$cookies', function($injector, $cookies) {
    var service = this;
    service.request = function(config) {
        if (!$cookies.get('access_token') && config.url.indexOf('myservice/oauth/token?grant_type=') === -1) {
            return $injector.get('mosServiceFactory').refresh_token().then(function(response) {
                var date = new Date();
                date.setTime(date.getTime() + (response.data.expiresIn * 1000));
                $cookies.remove('access_token');
                $cookies.put('access_token', response.data.value, {
                    expires: date
                });
                $cookies.put('refresh_token', response.data.refreshToken.value);
            }).then(function() {
                return config; // <-- token is refreshed, reissue original request
            });
        }
        return config;
    };

    service.responseError = function(response) {
        return response;
    };
}]);

Check the demo I was testing solution on to see how it recovers original request after token is loaded.

Demo: http://plnkr.co/edit/1Aey2PThZQ4Y8IRZuVOl?p=preview