Je sais comment intercepter TOUTES les demandes, mais je veux seulement intercepter les demandes de mes ressources.
Est-ce que quelqu'un sait comment faire ça?
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);
}
};
});
Si vous souhaitez intercepter uniquement les demandes provenant de ressources spécifiques, vous pouvez utiliser la propriété interceptor
facultative de l'action $request
. Documentation angulaire voir ici (Utilisation> 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
La seule façon pour moi de le faire consiste à filtrer les demandes que vous souhaitez dans le gestionnaire de réponses.
par exemple.
...
response: function(response) {
if(response.config.url.startsWith('/api/')) {
//Do your custom processing here
}
return response;
}
...
Polyfill pour 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;
};
}
Ma méthode préférée consiste à utiliser un intercepteur HTTP qui remplace un en-tête d'autorisation "magique" par le jeton OAuth actuel. Le code ci-dessous est spécifique à OAuth, mais y remédier est un exercice simple pour le lecteur.
// 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');
});
Je viens de rencontrer un problème où googleapis utilise également un en-tête Authorization
et renvoie une réponse 401 car le JWT que j'utilise sur mon serveur n'est pas valide pour leur serveur (évidemment), et mon code a été configuré pour supprimer automatiquement mon jeton et redirigez la personne vers la page de connexion. (Cela n'a pas été écrit très bien, car TOUTE réponse 401 déconnecterait mon utilisateur).
Je viens de trouver cette solution dans ma méthode request
dans l'intercepteur, qui, je pense, fonctionne plutôt bien:
.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);
}
}])
La méthode request
vérifie si j'ai un jeton dans le stockage localETsi l'URL de la demande est envoyée au même hôte (que je reçois de $location.Host()
) que celui sur lequel ma page est affichée. Cela fonctionne pour localhost ainsi que pour l’URL sur laquelle je déploie mon site.
Je n’ai pas fait beaucoup de tests avec cela, donc si quelqu'un trouve une faille dans ceci, faites-le moi savoir :)
/**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);
Par défaut, Angular envoie et reçoit les en-têtes application/json. Vous pouvez l'obtenir sur l'en-tête de réponse HTTP comme suit:
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);
}
};
});