2014-01-24 123 views
5

我使用角$ http拦截器来检查ajax请求是否返回401(未验证)。 如果响应是401,原始请求会排队,将显示一个登录表单,登录成功后会重试排队的请求。这已经与$ HTTP工作,并为角拦截的来源是:

define('common.service.security.interceptor', ['angular'], function() { 
'use strict'; 

angular.module('common.service.security.interceptor', ['common.service.security.retryQueue']) 

.factory('securityInterceptor', [ 
    '$injector', 
    '$location', 
    'securityRetryQueue', 
    function($injector, $location, securityRetryQueue) { 

     return function(promise) { 

      var $http = $injector.get('$http'); 


      // catch the erroneous requests 
      return promise.then(null, function(originalResponse){ 
       if(originalResponse.status === 401){ 
        promise = securityRetryQueue.pushRetryFn('Unauthorized', function retryRequest(){ 
         return $injector.get('$http')(originalResponse.config); 
        }); 
       } 

       return promise; 
      }); 
     }; 
    } 
]) 

// register the interceptor to the angular http service. method) 
.config(['$httpProvider', function($httpProvider) { 
    $httpProvider.responseInterceptors.push('securityInterceptor'); 

}]);}); 

我怎样才能让用这个角度$拦截HTTP请求的微风?

Breeze为文件“Breeze/Adapters/breeze.ajax.angular.js”中的角度$ http服务提供封装。所以,第一个想法是告诉微风使用它:

breeze.config.initializeAdapterInstance("ajax", "angular", true); 

调试angular.js,这表明现在的微风实际上使用$ HTTP,但它不执行上述注册拦截器。在$ http内部,有一个阵列“reversedInterceptors”,它包含已注册的拦截器。我将这个数组记录到控制台。如果我使用$ http,这个数组的长度是1(与预期的一样),但是当用微风发出请求时,这个数组是空的。

问题是,我如何使用$ HTTP拦截器和微风请求?

这里是breeze.ajax.angular.js代码,使用setHttp方法适用于我使用HTTP拦截随着微风角阿贾克斯适配器由微风

define('breeze.ajax.angular.module', ['breeze', 'angular'], function (breeze) { 
'use strict'; 
/* jshint ignore:start */ 
var core = breeze.core; 

var httpService; 
var rootScope; 

var ctor = function() { 
    this.name = "angular"; 
    this.defaultSettings = {}; 
}; 

ctor.prototype.initialize = function() { 

    var ng = core.requireLib("angular"); 

    if (ng) { 
     var $injector = ng.injector(['ng']); 
     $injector.invoke(['$http', '$rootScope', 
      function (xHttp, xRootScope) { 
       httpService = xHttp; 
       rootScope = xRootScope; 
     }]); 
    } 

}; 

ctor.prototype.setHttp = function (http) { 
    httpService = http; 
    rootScope = null; // to suppress rootScope.digest 
}; 

ctor.prototype.ajax = function (config) { 
    if (!httpService) { 
     throw new Error("Unable to locate angular for ajax adapter"); 
    } 
    var ngConfig = { 
     method: config.type, 
     url: config.url, 
     dataType: config.dataType, 
     contentType: config.contentType, 
     crossDomain: config.crossDomain 
    } 

    if (config.params) { 
     // Hack: because of the way that Angular handles writing parameters out to the url. 
     // so this approach takes over the url param writing completely. 
     // See: http://victorblog.com/2012/12/20/make-angularjs-http-service-behave-like-jquery-ajax/ 
     var delim = (ngConfig.url.indexOf("?") >= 0) ? "&" : "?"; 
     ngConfig.url = ngConfig.url + delim + encodeParams(config.params); 
    } 

    if (config.data) { 
     ngConfig.data = config.data; 
    } 

    if (!core.isEmpty(this.defaultSettings)) { 
     var compositeConfig = core.extend({}, this.defaultSettings); 
     ngConfig = core.extend(compositeConfig, ngConfig); 
    } 

    httpService(ngConfig).success(function (data, status, headers, xconfig) { 
     // HACK: because $http returns a server side null as a string containing "null" - this is WRONG. 
     if (data === "null") data = null; 
     var httpResponse = { 
      data: data, 
      status: status, 
      getHeaders: headers, 
      config: config 
     }; 
     config.success(httpResponse); 
    }).error(function (data, status, headers, xconfig) { 
     var httpResponse = { 
      data: data, 
      status: status, 
      getHeaders: headers, 
      config: config 
     }; 
     config.error(httpResponse); 
    }); 
    rootScope && rootScope.$digest(); 
}; 

function encodeParams(obj) { 
    var query = ''; 
    var key, subValue, innerObj; 

    for (var name in obj) { 
     var value = obj[name]; 

     if (value instanceof Array) { 
      for (var i = 0; i < value.length; ++i) { 
       subValue = value[i]; 
       fullSubName = name + '[' + i + ']'; 
       innerObj = {}; 
       innerObj[fullSubName] = subValue; 
       query += encodeParams(innerObj) + '&'; 
      } 
     } else if (value instanceof Object) { 
      for (var subName in value) { 
       subValue = value[subName]; 
       fullSubName = name + '[' + subName + ']'; 
       innerObj = {}; 
       innerObj[fullSubName] = subValue; 
       query += encodeParams(innerObj) + '&'; 
      } 
     } else if (value !== undefined) { 
      query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&'; 
     } 
    } 

    return query.length ? query.substr(0, query.length - 1) : query; 
} 


breeze.config.registerAdapter("ajax", ctor); 

breeze.config.initializeAdapterInstance("ajax", "angular", true); 
/* jshint ignore:end */ 
}); 

回答

6

提供。在我的环境,它看起来像这样:

(function() { 
    'use strict'; 

    var serviceId = 'entityManagerFactory'; 
    angular.module('app').factory(serviceId, ['$http', emFactory]); 

    function emFactory($http) { 

     var instance = breeze.config.initializeAdapterInstance("ajax", "angular"); 
     instance.setHttp($http); 

     ... 

    } 
})(); 

唯一的地方,我真的发现这方面有任何的信息是在1.4.4 download页面上的发行说明。我真的不明白这是什么。我相信其中一个微风家伙会有更好的解释。

+0

宾果! @almaplayer。 'setHttp' FTW。请参阅下面的答案。 – Ward

4

您必须致电setHttp($http),如@almaplayera所述。请将他标为正确的答案。

这就是为什么这是必要的。

默认情况下,breeze angular ajax适配器使用$ http的任何实例初始化本身。不幸的是,当大多数脚本加载时,您的APP的$http实例尚未创建。这不会发生,直到你的模块加载...这通常发生在微风加载后很长时间。

因此,不是创建一个根本不起作用的适配器,而是微风旋转自己的$http实例并将角度ajax适配器连接到该实例。

如果你的代码没有做任何特殊的事情,这可以正常工作。这不是最佳的;你会得到一个额外的$digest周期比必要的。但它适用于大多数人,让我们承认有足够的配置噪音来处理。

但是你正在做一些特别的事情。您正在配置一个非常具体的$http实例,而不是微风为自己创建的实例。

所以你必须告诉微风使用$http的实例......这就是当你拨打setHttp($http)时发生的情况;

感谢此反馈,我更新了breeze documentation on ajax adapters来描述如何配置Angular应用程序。