---恢復內容開始---
任何時候如果我們想要為請求添加全局功能,例如身份驗證、錯誤處理等,在請求發送給服務器之前或者從服務器返回時對其進行攔截,是比較好的實現手段。
例如對於身份驗證,如果服務器返回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'); }])
---恢復內容結束---
