如何使用angularJS拦截器来拦截特定的http请求?

时间:2014-04-11 19:51:22

标签: angularjs angularjs-service

我知道如何拦截所有请求,但我只想拦截来自我资源的请求。

有谁知道怎么做?

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);
      }
    };
  });

7 个答案:

答案 0 :(得分:23)

我知道这样做的唯一方法就是在响应处理程序中过滤掉你想要的请求。

e.g。

...
response: function(response) {
    if(response.config.url.startsWith('/api/')) {
        //Do your custom processing here
    }

    return response;
}
...

polyfill for 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;
    };
}

答案 1 :(得分:23)

如果您只想拦截来自特定资源的请求,则可以使用interceptor操作的可选$request属性。 Angular的文档see here(用法>操作)

<强>的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

答案 2 :(得分:0)

/**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);

答案 3 :(得分:0)

我首选的方法是使用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');
});

答案 4 :(得分:0)

默认情况下,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);
      }
    };
  });

答案 5 :(得分:0)

我刚刚遇到一个问题,其中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。

我没有做太多测试,所以如果有人发现这方面的缺陷,请告诉我:)

答案 6 :(得分:0)

我知道这是一个古老的问题,但是如果您已推送多个$ 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);
                }
            }
        };
    }]);