问题
I know how to intercept ALL requests, but I only want to intercept requests from my resources.
Does anyone know how to do this?
services.config(['$httpProvider',function($httpProvider) {
$httpProvider.interceptors.push('myHttpInterceptor');
}]);
services.factory("userPurchased", function ($resource) {
return $resource("/api/user/purchases/:action/:item",
{},
{
'list': {method: 'GET', params: {action: 'list'}, isArray: false},
'save': {method: 'PUT', params: {item: '@item'}},
'remove': {method: 'DELETE', params: {item: '@item'}},
}
);
});
services.factory('myHttpInterceptor', function($q,$rootScope) {
// $rootScope.showSpinner = false;
return {
response: function(response) {
$rootScope.showSpinner = false;
// do something on success
console.log('success');
console.log('status', response.status);
//return response;
return response || $q.when(response);
},
responseError: function(response) {
// do something on error
$rootScope.showSpinner = true;
console.log('failure');
console.log('status', response.status)
//return response;
return $q.reject(response);
}
};
});
回答1:
If you want to intercept only requests from specific resources, you can use optional interceptor
property of $request
action. Angular's documentation see here (Usage>actions)
JavaScript
angular.module('app', ['ngResource']).
factory('resourceInterceptor', function() {
return {
response: function(response) {
console.log('response intercepted: ', response);
}
}
}).
factory('resourceService', ['$resource', 'resourceInterceptor', function($resource, resourceInterceptor) {
return $resource(":name",
{},
{
'list': {method: 'GET', isArray: false, interceptor: resourceInterceptor}
}
);
}]).
run(['resourceService', '$http', function(resourceService, $http) {
resourceService.list({name: 'list.json'}); // <= intercepted
$http.get('list.json'); // <= not intercepted
}]);
Plunker: http://plnkr.co/edit/xjJH1rdJyB6vvpDACJOT?p=preview
回答2:
The only way I know of doing this it to just filter out the requests you want in the response handler.
e.g.
...
response: function(response) {
if(response.config.url.startsWith('/api/')) {
//Do your custom processing here
}
return response;
}
...
Polyfill for string.startsWith()
//Taken from http://stackoverflow.com/questions/646628/javascript-startswith
if (typeof(String.prototype.startsWith) === 'undefined') {
String.prototype.startsWith = function(str) {
return this.slice(0, str.length) === str;
};
}
回答3:
/**object single interceptor**/
function SingleCallInterceptor(callbacks){
this.receive=function(response) {
switch (response.status) {
case 200:
callbacks.success(apiResponse);
break;
default :
callbacks.error(response);
}
}
}
var successfn=function(response){ //i have my response}
var errorfn=function(response){ //i have my error}
var responseInterceptor=new SingleCallInterceptor({success:successfn,error:errorfn});
$http({
url: "www.itsdirtysolutioniknow.it,
method: "GET",
dataType: "JSONP",
}).then(responseInterceptor.receive,responseInterceptor.receive);
回答4:
My preferred way is to use an HTTP interceptor which replaces a "magic" Authorization header with the current OAuth token. The code below is OAuth specific, but remedying that is a simple exercise for the reader.
// Injects an HTTP interceptor that replaces a "Bearer" authorization header
// with the current Bearer token.
module.factory('oauthHttpInterceptor', function (OAuth) {
return {
request: function (config) {
if (config.headers.Authorization === 'Bearer') {
config.headers.Authorization = 'Bearer ' + btoa(OAuth.accessToken);
}
return config;
}
};
});
module.config(function ($httpProvider) {
$httpProvider.interceptors.push('oauthHttpInterceptor');
});
回答5:
By default angular sends and receives application/json headers. You can get this on the HTTP response header like :
services.config(['$httpProvider',function($httpProvider) {
$httpProvider.interceptors.push('myHttpInterceptor');
}]);
services.factory("userPurchased", function ($resource) {
return $resource("/api/user/purchases/:action/:item",
{},
{
'list': {method: 'GET', params: {action: 'list'}, isArray: false},
'save': {method: 'PUT', params: {item: '@item'}},
'remove': {method: 'DELETE', params: {item: '@item'}},
}
);
});
services.factory('myHttpInterceptor', function($q,$rootScope) {
// $rootScope.showSpinner = false;
return {
response: function(response) {
// use this line to if you are receiving json, else use xml or any other type
var isJson = response.config.headers.Accept.indexOf('json')>-1;
$rootScope.showSpinner = false;
// do something on success
console.log('success');
console.log('status', response.status);
//return response;
return response || $q.when(response);
},
responseError: function(response) {
// use this line to if you are receiving json, else use xml or any other type
var isJson = response.config.headers.Accept.indexOf('json')>-1;
// do something on error
$rootScope.showSpinner = true;
console.log('failure');
console.log('status', response.status)
//return response;
return $q.reject(response);
}
};
});
回答6:
I just came across an issue where googleapis also uses an Authorization
header, and was throwing a 401 response because the JWT I use on my server wasn't valid for their server (obviously), and my code was set to automatically remove my token and redirect the person to the login page. (It wasn't written super well, since ANY 401 response would log my user out).
I just came up with this solution in my request
method in the interceptor, which I think works pretty well:
.service('authInterceptor', ["$q", "$location", "tokenService", function($q, $location, tokenService){
this.request = function(config) {
// console.log($location.host());
var token = tokenService.getToken();
if(token && config.url.indexOf($location.host()) > -1) {
config.headers = config.headers || {};
config.headers.Authorization = "Bearer " + token
}
return config
}
this.responseError = function(response) {
// console.log(response.config.url)
if (response.status === 401) {
tokenService.removeToken();
$location.path('/login')
}
return $q.reject(response);
}
}])
The request
method checks if I have a token in local storage AND if the request url is being made to the same host (which I get from $location.host()
) as the one my page is being served up on. This works for localhost as well as whatever URL I end up deploying my site on.
I haven't done much testing with this, so if anyone finds a flaw in this please let me know :)
回答7:
I know it is an old question but I wanted to provide a solution if you have pushed multiple $http Interceptors and want them to continue working, return your response so the Interceptor chain continues:
module.factory('resourceInterceptor', ['$q', function($q) {
return {
response: function(response) {
// do your conditional logic here
if (...) {
return $q.resolve(response);
}
},
responseError: function(response) {
// do your conditional logic here
if (...) {
return $q.reject(response);
}
}
};
}]);
来源:https://stackoverflow.com/questions/23021416/how-to-use-angularjs-interceptor-to-only-intercept-specific-http-requests