---恢復內容開始---
任何時候如果我們想要為請求添加全局功能,例如身份驗證、錯誤處理等,在請求發送給服務器之前或者從服務器返回時對其進行攔截,是比較好的實現手段。
例如對於身份驗證,如果服務器返回401狀態碼,我們會希望將用戶重定向到登錄頁面。AngularJS通過攔截器提供了一個從全局層面對響應進行處理的途徑。攔截器,盡管名字聽起來很唬人,實際上是$http服務的基礎中間件,用來向應用的業務流程中注入新的邏輯。攔截器的核心是服務工廠(查看第14章獲得更多關於服務的信息),通過向$httpProvider.interceptors數組中添加服務工廠,在$httpProvider中進行注冊。一共有四種攔截器,兩種成功攔截器,兩種失敗攔截器。
Request
AngularJS通過$http設置對象來對請求攔截器進行調用。它可以對設置對象進行修改,或者創建一個新的設置對象,它需要返回一個更新過的設置對象,或者一個可以返回新的設置對象的promise。
Response
AngularJS通過$http設置對象來對響應攔截器進行調用。它可以對響應進行修改,或者創建一個新的響應,它需要返回一個更新過的響應,或者一個可以返回新響應的promise
requestError
AngularJS會在上一個請求攔截器拋出錯誤,或者promise被reject時調用此攔截器。
responseError
AngularJS會在上一個響應攔截器拋出錯誤,或者promise被reject時調用此攔截器
調用模塊的.factory()方法來創建攔截器,可以在服務中添加一種或多種攔截器
MyApp.factory('authHttpResponseInterceptor', ["$rootScope", "myCookie", '$q', '$location', "$routeParams", function ($rootScope, myCookie, $q, $location,$routeParams) { //攔截器配置 return { request: function (config) { var url = config.url; //請求通用配置(添加token) if(url.indexOf("access/login") != -1 || url.indexOf("access/authorize") != -1){ }else if(myCookie("access_token") !== null){ config.headers['access_token'] = myCookie("access_token"); }else if(url.indexOf("rest/") != -1 || (url.indexOf("teacher/") != -1 && url.indexOf(".html") != -1) || (url.indexOf("student/") != -1 && url.indexOf(".html") != -1)){ //未登錄認證 config.url = "unknown"; } $rootScope.currUrl = config.url; return config || $q.when(config); }, response: function(response){ //本地url權限認證 var browserUrl = $location.path(); var stuUrls = ["/stuexam","/stuquestion","/user/bound"];//學生url定義 var commonUrls = ["/404","/busy","/about","/secure","/user"];//公共url定義 var commonUrlLen = commonUrls.length; var isCommon = false;//是否是公共url if(browserUrl == "/"){ isCommon = true; }else{ for(urlIndex=0;urlIndex<commonUrlLen;urlIndex++){ var uri = commonUrls[urlIndex]; if(browserUrl.indexOf(uri) === 0){ isCommon = true; break; } } } if(!isCommon && myCookie("accountType") !== null){ var accountType = myCookie("accountType"); if(accountType == "teacher"){ if(browserUrl.indexOf("/stuexam") === 0 || browserUrl.indexOf("/stuquestion") === 0){ $location.path('404'); } }else if(accountType == "student"){ if(browserUrl.indexOf("/stuexam") !== 0 && browserUrl.indexOf("/stuquestion") !== 0){ $location.path('404'); } //驗證是否是訪問的當前學生的數據 if(browserUrl.indexOf("/stuexam/analysis") === 0 || browserUrl.indexOf("/stuexam/paper") === 0){ var studentId = myCookie("accountId"); if(browserUrl.lastIndexOf("/") != browserUrl.length - 1){ browserUrl = browserUrl.substring(0,browserUrl.length); } var urlStuId = browserUrl.substring(browserUrl.lastIndexOf("/")+1); if(studentId !== urlStuId){//訪問非當前學生數據 $location.path('404'); } } } } return response || $q.when(response); }, responseError: function(rejection) { var currUrl = $rootScope.currUrl; //請求返回異常類型判斷 if(currUrl !== null && currUrl == "unknown"){ $location.path('/'); }else if (rejection.status == 401) { if(rejection.data !== null && (rejection.data.message == "No access_token" || rejection.data.message == "Invalid token, token has expired!" || rejection.data.message == "Unknown token!")){ $location.path('/'); }else if(currUrl.indexOf("access/") == -1){ $location.path('404');//.search('returnTo', $location.path()); } }else if (rejection.status == 404) { $location.path('404');//.search('returnTo', $location.path()); }else if (rejection.status == 412) { // if(currUrl.indexOf("register")==-1&&currUrl.indexOf("bind")==-1&&currUrl.indexOf("resetPassword")==-1){ // $location.path('busy'); // } }else if (rejection.status != 200) { if(currUrl.indexOf("register")==-1&&currUrl.indexOf("bind")==-1&&currUrl.indexOf("resetPassword")==-1){ $location.path('busy'); } } return $q.reject(rejection); } }; }])
我們需要使用$httpProvider在.config()函數中注冊攔截器:
MyApp.config(['$httpProvider', function ($httpProvider) { //Http Intercpetor to check auth failures for xhr requests $httpProvider.interceptors.push('authHttpResponseInterceptor'); }])
---恢復內容結束---