溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Angular.js中$http攔截器有什么用

發(fā)布時間:2021-07-09 11:00:18 來源:億速云 閱讀:199 作者:小新 欄目:web開發(fā)

這篇文章主要介紹了Angular.js中$http攔截器有什么用,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

前言

$http service在Angular中用于簡化與后臺的交互過程,其本質上使用XMLHttpRequest或JSONP進行與后臺的數(shù)據(jù)交互。在與后臺的交互過程中,可能會對每條請求發(fā)送到Server之前進行預處理(如加入token),或者是在Server返回數(shù)據(jù)到達客戶端還未被處理之前進行預處理(如將非JSON格式數(shù)據(jù)進行轉換);當然還有可能對在請求和響應過程過發(fā)生的問題進行捕獲處理。所有這些需求在開發(fā)中都非常常見,所以Angular為我們提供了$http攔截器,用來實現(xiàn)上述需求。

什么是攔截器

顧名思義,攔截器就是在目標達到目的地之前對其進行處理以便處理結果更加符合我們的預期。Angular的$http攔截器是通過$httpProvider.interceptors數(shù)組定義的一組攔截器,每個攔截器都是實現(xiàn)了某些特定方法的Factory:

Angular.js中$http攔截器有什么用

實現(xiàn)攔截器

http攔截器一般通過定義factory的方式實現(xiàn):

myApp.factory('MyInterceptor', function($q) {
 return {
 // 可選,攔截成功的請求
 request: function(config) {
  // 進行預處理
  // ...
  return config || $q.when(config);
 },

 // 可選,攔截失敗的請求
 requestError: function(rejection) {
  // 對失敗的請求進行處理
  // ...
  if (canRecover(rejection)) {
  return responseOrNewPromise
  }
  return $q.reject(rejection);
 },



 // 可選,攔截成功的響應
 response: function(response) {
  // 進行預處理
  // ....
  return response || $q.when(reponse);
 },

 // 可選,攔截失敗的響應
 responseError: function(rejection) {
  // 對失敗的響應進行處理
  // ...
  if (canRecover(rejection)) {
  return responseOrNewPromise
  }
  return $q.reject(rejection);
 }
 };
});

隨后,我們需要將實現(xiàn)的攔截器加入到$httpProvider.interceptors數(shù)組中,此操作一般在config方法中進行:

myApp.config(function($httpProvider) {
 $httpProvider.interceptors.push(MyInterceptor);
});

當然,我們也可以通過匿名factroy的方式實現(xiàn):

$httpProvider.interceptors.push(function($q) {
 return {
 request: function(config) {
  // bala
 },

 response: function(response) {
  // bala
 },

 // bala
 };
});

可以看到,每個攔截器都可以實現(xiàn)4個可選的處理函數(shù),分別對應請求(成功/失敗)和響應(成功/失?。┑臄r截:

1、request:此函數(shù)在$http向Server發(fā)送請求之前被調用,在此函數(shù)中可以對成功的http請求進行處理,其包含一個http config對象作為參數(shù),這里對config對象具有完全的處理權限,甚至可以重新構造,然后直接返回此對象或返回包含此對象的promise即可。如果返回有誤,會造成$http請求失敗。如開發(fā)中經常需要在請求頭中加入token以便驗證身份,我們可以作如下處理:

request: function(config) {
 config.headers = config.headers || {};
 if ($window.sessionStorage.token) {
  config.headers['X-Access-Token'] = $window.sessionStorage.token;
 }
 return config || $q.when(config);
}

2、requestError:此方法會在前一個攔截器拋出異常或進行了reject操作時被調用,在這里可以進行恢復請求的操作,或者進行一些對于請求時發(fā)起動作的處理(如取消loading等);

3、response:此函數(shù)在$http從Server接收到響應時被調用,在此函數(shù)中可以對成功的http響應進行處理,這里具有對響應的完全處理權限,甚至可以重新構造,然后直接返回響應或返回包含響應的promise即可。如果返回有誤,會造成$http接收響應失??;

4、responseError:此方法會在前一個攔截器拋出異常或進行了reject操作時被調用,在這里可以進行恢復響應的操作,進行一些針對錯誤的處理。

使用用例

為演示Angular $http攔截器的使用方法,下面通過幾個常用的用例來說明:

利用request攔截器模擬實現(xiàn)Angular的XSRF(即CSRF)防御

CSRF,即“跨站請求偽造”,不過不知道為什么Angular將其稱為XSRF。當處理與后臺交互時,Angular的$http會嘗試從客戶端cookie中讀取一個token,其默認的key為XSRF-TOKEN,并構造一個名為X-XSRF-TOKEN的http頭部,與http請求一起發(fā)送到后臺。Server端就可以根據(jù)此token識別出請求來源于同域,當然跨域的請求$http不會加入X-XSRF-TOKEN頭部。那我們可以利用request攔截器通過如下方式在同域請求頭部中加入此頭部以達到模擬Angular的XSRF(即CSRF)防御機制的實現(xiàn)效果:

/**
* 正式開發(fā)中Angular會主動進行XSRF防御(只要cookie中存在key為`XSRF-TOKEN`的token),
* 一般不需要手動進行,除非cookie中不存在key為`XSRF-TOKEN`的token,這里只是模擬實現(xiàn)
*/
request: function(config) {
 if(config.url.indexOf('SAME_DOMAIN_API_URL') > -1) {
 config.headers['X-XSRF-TOKEN'] = $cookies.get('XSRF-TOKEN');
 }
 return config;
}

如果初始http請求頭部類似于:

"headers": {
 "Accept": "application/json, text/plain, */*"
}

那么經過上述的攔截器后,其http請求頭部就變成了:

"headers": {
 "Accept": "application/json, text/plain, */*",
 "X-XSRF-TOKEN": X-XSRF-TOKEN-VALUE
}

利用response攔截器模擬實現(xiàn)Angular JSON易損性(JSON vulnerability)防御

Angular在$http請求安全性方面不僅為我們設計了XSRF(CSRF)防御,而且針對請求JSON數(shù)據(jù)的Url可能通過類似于<script>標簽加載的方式被惡意網站獲取到我們的JSON數(shù)據(jù)的情況,設計了Angular JSON易損性(JSON vulnerability)防御,即Server端返回的JSON數(shù)據(jù)頭部可以添加")]}',\n"字符串,得到包含此前綴的響應數(shù)據(jù)后,Angular會將此前綴刪去,將響應還原成正式的JSON數(shù)據(jù)。此時我們就可以通過response攔截器模擬此過程:

response: function(response) {
 var data = examineJSONResponse(response); // 假設存在這樣一個方法
 if(!data) {
  response = validateJSONResponse(response); // 假設存在這樣一個方法
 }
 return response || $q.when(reponse);
}

利用request攔截器和response攔截器計算http請求耗時

這個需求可能在開發(fā)中并不常用,這里只是作為同時使用request攔截器和response攔截器的例子,我們可以在request攔截器和response攔截器中分別計時,然后求得其差值即可:

myApp.factory('timestampMarker', [function() {
 return {
  request: function(config) {
   config.requestTimestamp = new Date().getTime();
   return config;
  },
  response: function(response) {
   response.config.responseTimestamp = new Date().getTime();
   return response;
  }
 };
}]);
myApp.config(['$httpProvider', function($httpProvider) {
 $httpProvider.interceptors.push('timestampMarker');
}]);

這樣我們在每次請求后臺時,就能夠計算出相應請求的耗時了,如:

$http.get('https://api.github.com/users/liuwenzhuang/repos').then(function(response) {
 var time = response.config.responseTimestamp - response.config.requestTimestamp;
 console.log('The request took ' + (time / 1000) + ' seconds.');
});

感謝你能夠認真閱讀完這篇文章,希望小編分享的“Angular.js中$http攔截器有什么用”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業(yè)資訊頻道,更多相關知識等著你來學習!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。

AI