すべてのリクエストをインターセプトする方法は知っていますが、リソースからのリクエストのみをインターセプトしたいです。
誰もこれを行う方法を知っていますか?
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);
}
};
});
特定のリソースからのリクエストのみをインターセプトする場合は、$request
アクションのオプションのinterceptor
プロパティを使用できます。 Angularのドキュメント こちらを参照 (使用法>アクション)
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
}]);
私がこれを行うことを知っている唯一の方法は、応答ハンドラで必要な要求をフィルタリングするだけです。
例えば.
...
response: function(response) {
if(response.config.url.startsWith('/api/')) {
//Do your custom processing here
}
return response;
}
...
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;
};
}
私の好ましい方法は、HTTPインターセプターを使用して、「マジック」認証ヘッダーを現在のOAuthトークンに置き換えます。以下のコードはOAuth特定ですが、これは読者にとって簡単な練習です。
// 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');
});
GoogleapisもAuthorization
ヘッダーを使用し、サーバーで使用するJWTが(明らかに)サーバーに対して有効ではなく、コードがトークンを自動的に削除し、ユーザーをログインページにリダイレクトします。 (401の応答はユーザーをログアウトさせるため、非常にうまく書かれていませんでした)。
インターセプターのrequest
メソッドでこのソリューションを思いついたところです。
_.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);
}
}])
_
request
メソッドは、ローカルストレージにトークンがあるかどうかを確認します[〜#〜] and [〜#〜]リクエストURLが同じホストに対して作成されているかどうか(取得します) $location.Host()
)から私のページが提供されているものとして。これは、localhostだけでなく、サイトを展開するURLでも機能します。
私はこれで多くのテストを行っていないので、誰かがこれに欠陥を見つけたら私に知らせてください:)
/**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);
デフォルトではangular application/jsonヘッダーを送受信します。これは、次のようなHTTP応答ヘッダーで取得できます。
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);
}
};
});
私はそれが古い質問であることを知っていますが、複数の$ httpインターセプターをプッシュし、それらが動作し続けるようにしたい場合は、インターセプターチェーンが継続するように応答を返します。
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);
}
}
};
}]);