18

How can I stop a request in Angularjs interceptor.

Is there any way to do that?

I tried using promises and sending reject instead of resolve !

.factory('connectionInterceptor', ['$q', '$timeout',
   function($q, $timeout) {
    var connectionInterceptor = {
        request: function(config) {
            var q = $q.defer();
            $timeout(function() {
                q.reject();
            }, 2000)
            return q.promise;
            // return config;
        }
    }
    return connectionInterceptor;
  }
])
.config(function($httpProvider) {
   $httpProvider.interceptors.push('connectionInterceptor');
});
7
  • 1
    Post the code that you tried. Otherwise, we have no way of explaining you why it doesn't work, and how to fix it. Commented Aug 24, 2014 at 15:57
  • @JBNizet added ! Please check the code ! Commented Aug 24, 2014 at 17:07
  • Not sure why you're waiting 2 seconds, but your code works fine. No HTTP request is sent. See plnkr.co/edit/x4YGC7l4B66RGTmWB7Ts?p=preview. Open your dev tools, and check your network tab: no request to README is sent. Now comment out the registration of the interceptor and do the same test, and you'll see the request going out, and the success alert displayed. Commented Aug 24, 2014 at 17:19
  • 2
    Well, be aware that ALL ajax requests go through your interceptor, including the ones loading the html templates. If that's not the problem, post a plunkr that reproduces the problem. Commented Aug 24, 2014 at 17:30
  • 1
    check the value of config.url. Commented Aug 24, 2014 at 17:36

5 Answers 5

10

I ended up bypassing angular XHR call with the following angular Interceptor:

function HttpSessionExpiredInterceptor(sessionService) {
    return {
        request: function(config) {
            if (sessionService.hasExpired()) {
                /* Avoid any other XHR call. Trick angular into thinking it's a GET request.
                 * This way the caching mechanism can kick in and bypass the XHR call.
                 * We return an empty response because, at this point, we do not care about the
                 * behaviour of the app. */
                if (_.startsWith(config.url, '/your-app-base-path/')) {
                    config.method = 'GET';
                    config.cache = {
                        get: function() {
                            return null;
                        }
                    };
                }
            }

            return config;
        }
    };
}

This way, any request, POST, PUT, ... is transformed as a GET so that the caching mechanism can be used by angular. At this point, you can use your own caching mechanism, in my case, when session expires, I do not care anymore about what to return.

Sign up to request clarification or add additional context in comments.

1 Comment

I know this is an old answer, but this is very clever.
7

The $http service has an options timeout to do the job. you can do like:

angular.module('myApp')
    .factory('httpInterceptor', ['$q', '$location',function ($q, $location) {
        var canceller = $q.defer();
        return {
            'request': function(config) {
                // promise that should abort the request when resolved.
                config.timeout = canceller.promise;
                return config;
            },
            'response': function(response) {
                return response;
            },
            'responseError': function(rejection) {
                if (rejection.status === 401) {
                    canceller.resolve('Unauthorized'); 
                    $location.url('/user/signin');
                }
                if (rejection.status === 403) {
                    canceller.resolve('Forbidden');  
                    $location.url('/');
                }
                return $q.reject(rejection);
            }

        };
    }
    ])
    //Http Intercpetor to check auth failures for xhr requests
   .config(['$httpProvider',function($httpProvider) {
        $httpProvider.interceptors.push('httpInterceptor');
    }]);

Comments

1

Not sure if it is possible in general. But you can start a $http request with a "canceler".

Here is an example from this answer:

var canceler = $q.defer();
$http.get('/someUrl', {timeout: canceler.promise}).success(successCallback);
// later...
canceler.resolve();  // Aborts the $http request if it isn't finished.

So if you have control over the way that you start your request, this might be an option.

2 Comments

I want a generalised solution using interceptors !
@vipulsodha Whisher's answer seems like a nice implementation of the idea.
1

Here is what works for me, especially for the purposes of stopping the outgoing request, and mocking the data:


app
  .factory("connectionInterceptor", [
    "$q",
    function ($q) {
      return {
        request: function (config) {
          // you can intercept a url here with (config.url == 'https://etc...') or regex or use other conditions
          if ("conditions met") {
            config.method = "GET";
            // this is simulating a cache object, or alternatively, you can use a real cache object and pre-register key-value pairs,
            // you can then remove the if block above and rely on the cache (but your cache key has to be the exact url string with parameters)
            config.cache = {
              get: function (key) {
                // because of how angularjs $http works, especially older versions, you need a wrapping array to get the data
                // back properly to your methods (if your result data happens to be an array). Otherwise, if the result data is an object
                // you can pass back that object here without any return codes, status, or headers.
                return [200, mockDataResults, {}, "OK"];
              },
            };
          }
          return config;
        },
      };
    },
  ])
  .config(function ($httpProvider) {
    $httpProvider.interceptors.push("connectionInterceptor");
  });

If you are trying to mock a result like

[42, 122, 466]

you need to send an array with some http params back, its just how the ng sendReq() function is written unfortunately. (see line 1414 of https://github.com/angular/angular.js/blob/e41f018959934bfbf982ba996cd654b1fce88d43/src/ng/http.js#L1414 or snippet below)

        // from AngularJS http.js

        // serving from cache
        if (isArray(cachedResp)) {
          resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3], cachedResp[4]);
        } else {
          resolvePromise(cachedResp, 200, {}, 'OK', 'complete');
        }

Comments

0

I just ended up in returning as an empty object

'request': function request(config) {
    if(shouldCancelThisRequest){  
        return {};
    }
    return config;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.