Skip to content

Commit

Permalink
chore($http): remove deprecated responseInterceptors functionality
Browse files Browse the repository at this point in the history
Code cleanup! response interceptors have been deprecated for some time, and it is confusing to have
two APIs, one of which is slightly "hidden" and hard to see, which perform the same task. The newer
API is a bit cleaner and more visible, so this is naturally preferred.

BREAKING CHANGE:

Previously, it was possible to register a response interceptor like so:

    // register the interceptor as a service
    $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
      return function(promise) {
        return promise.then(function(response) {
          // do something on success
          return response;
        }, function(response) {
          // do something on error
          if (canRecover(response)) {
            return responseOrNewPromise
          }
          return $q.reject(response);
        });
      }
    });

    $httpProvider.responseInterceptors.push('myHttpInterceptor');

Now, one must use the newer API introduced in v1.1.4 (4ae4681), like so:

    $provide.factory('myHttpInterceptor', function($q) {
      return {
        response: function(response) {
          // do something on success
          return response;
        },
        responseError: function(response) {
          // do something on error
          if (canRecover(response)) {
            return responseOrNewPromise
          }
          return $q.reject(response);
        }
      };
    });

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

More details on the new interceptors API (which has been around as of v1.1.4) can be found at
https://docs.angularjs.org/api/ng/service/$http#interceptors

Closes angular#7266
  • Loading branch information
caitp committed Apr 27, 2014
1 parent accd35b commit 67cd227
Show file tree
Hide file tree
Showing 2 changed files with 1 addition and 193 deletions.
72 changes: 0 additions & 72 deletions src/ng/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,6 @@ function $HttpProvider() {
*/
var interceptorFactories = this.interceptors = [];

/**
* For historical reasons, response interceptors are ordered by the order in which
* they are applied to the response. (This is the opposite of interceptorFactories)
*/
var responseInterceptorFactories = this.responseInterceptors = [];

this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',
function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {

Expand All @@ -149,27 +143,6 @@ function $HttpProvider() {
? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory));
});

forEach(responseInterceptorFactories, function(interceptorFactory, index) {
var responseFn = isString(interceptorFactory)
? $injector.get(interceptorFactory)
: $injector.invoke(interceptorFactory);

/**
* Response interceptors go before "around" interceptors (no real reason, just
* had to pick one.) But they are already reversed, so we can't use unshift, hence
* the splice.
*/
reversedInterceptors.splice(index, 0, {
response: function(response) {
return responseFn($q.when(response));
},
responseError: function(response) {
return responseFn($q.reject(response));
}
});
});


/**
* @ngdoc service
* @kind function
Expand Down Expand Up @@ -422,51 +395,6 @@ function $HttpProvider() {
* });
* ```
*
* # Response interceptors (DEPRECATED)
*
* Before you start creating interceptors, be sure to understand the
* {@link ng.$q $q and deferred/promise APIs}.
*
* For purposes of global error handling, authentication or any kind of synchronous or
* asynchronous preprocessing of received responses, it is desirable to be able to intercept
* responses for http requests before they are handed over to the application code that
* initiated these requests. The response interceptors leverage the {@link ng.$q
* promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.
*
* The interceptors are service factories that are registered with the $httpProvider by
* adding them to the `$httpProvider.responseInterceptors` array. The factory is called and
* injected with dependencies (if specified) and returns the interceptor — a function that
* takes a {@link ng.$q promise} and returns the original or a new promise.
*
* ```js
* // register the interceptor as a service
* $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
* return function(promise) {
* return promise.then(function(response) {
* // do something on success
* return response;
* }, function(response) {
* // do something on error
* if (canRecover(response)) {
* return responseOrNewPromise
* }
* return $q.reject(response);
* });
* }
* });
*
* $httpProvider.responseInterceptors.push('myHttpInterceptor');
*
*
* // register the interceptor via an anonymous factory
* $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {
* return function(promise) {
* // same as above
* }
* });
* ```
*
*
* # Security Considerations
*
* When designing web applications, consider security threats from:
Expand Down
122 changes: 1 addition & 121 deletions test/ng/httpSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,29 +28,6 @@ describe('$http', function() {

describe('$httpProvider', function() {
describe('interceptors', function() {
it('should accept injected rejected response interceptor', function() {
var wasCalled = false;
module(function($httpProvider, $provide) {
$httpProvider.responseInterceptors.push('injectedInterceptor');
$provide.factory('injectedInterceptor', ['$q', function($q) {
return function(promise) {
return promise.then(null, function authInterceptor(response) {
wasCalled = true;
expect(response.status).toEqual(401);
return $q.reject(response);
});
};
}]);
});
inject(function($http, $httpBackend) {
$httpBackend.expect('GET', '/url').respond(401);
$http({method: 'GET', url: '/url'});
$httpBackend.flush();
expect(wasCalled).toEqual(true);
});
});


it('should chain request, requestReject, response and responseReject interceptors', function() {
module(function($httpProvider) {
var savedConfig, savedResponse;
Expand Down Expand Up @@ -128,28 +105,6 @@ describe('$http', function() {
}
};
});
$httpProvider.responseInterceptors.push(function($q) {
return function(promise) {
var defer = $q.defer();

promise.then(function(response) {
response.data = '[' + response.data + '] legacy-1';
defer.resolve(response);
});
return defer.promise;
};
});
$httpProvider.responseInterceptors.push(function($q) {
return function(promise) {
var defer = $q.defer();

promise.then(function(response) {
response.data = '[' + response.data + '] legacy-2';
defer.resolve(response);
});
return defer.promise;
};
});
});
inject(function($http, $httpBackend) {
var response;
Expand All @@ -158,82 +113,7 @@ describe('$http', function() {
response = r;
});
$httpBackend.flush();
expect(response.data).toEqual('{{[[response] legacy-1] legacy-2} inner} outer');
});
});
});


describe('response interceptors', function() {

it('should default to an empty array', module(function($httpProvider) {
expect($httpProvider.responseInterceptors).toEqual([]);
}));


it('should pass the responses through interceptors', function() {
module(function($httpProvider, $provide) {
$provide.factory('testInterceptor', function ($q) {
return function(httpPromise) {
return httpPromise.then(function(response) {
var deferred = $q.defer();
deferred.resolve({
data: response.data + '?',
status: 209,
headers: response.headers,
request: response.config
});
return deferred.promise;
});
};
});
// just change the response data and pass the response object along
$httpProvider.responseInterceptors.push(function() {
return function(httpPromise) {
return httpPromise.then(function(response) {
response.data += '!';
return response;
});
};
});

// return a new resolved promise representing modified response object
$httpProvider.responseInterceptors.push('testInterceptor');
});
inject(function($http, $httpBackend) {
$httpBackend.expect('GET', '/foo').respond(201, 'Hello');
$http.get('/foo').success(function(data, status) {
expect(data).toBe('Hello!?');
expect(status).toBe(209);
callback();
});
$httpBackend.flush();
expect(callback).toHaveBeenCalledOnce();
});
});


it('should support interceptors defined as services', function() {
module(function($provide, $httpProvider) {
$provide.factory('myInterceptor', function() {
return function(promise) {
return promise.then(function(response) {
response.data = uppercase(response.data);
return response;
});
};
});
$httpProvider.responseInterceptors.push('myInterceptor');
});
inject(function($http, $httpBackend) {
var response;

$httpBackend.expect('GET', '/test').respond('hello!');
$http.get('/test').success(function(data) {response = data;});
expect(response).toBeUndefined();

$httpBackend.flush();
expect(response).toBe('HELLO!');
expect(response.data).toEqual('{{response} inner} outer');
});
});
});
Expand Down

0 comments on commit 67cd227

Please sign in to comment.