简体   繁体   English

微风使用角$ http拦截器

[英]Breeze using angular $http interceptor

I use a angular $http interceptor, to check if a ajax request returns 401 (not authenticated). 我使用一个有角度的$ http拦截器来检查ajax请求是否返回401(未经过身份验证)。 If response is 401, the original request gets queued, a login form is shown and after login successfully, it retries the queued requests. 如果响应为401,则原始请求排队,显示登录表单,登录成功后,将重试排队的请求。 This already works with $http, and the source for the angular interceptor is: 这已经与$ 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');

}]);});

How can I make breeze request using this angular $http interceptor? 如何使用这个有角度的$ http拦截器创建breeze请求?

Breeze provides a wrapper for the angular $http service in the file "Breeze/Adapters/breeze.ajax.angular.js". Breeze为文件“Breeze / Adapters / breeze.ajax.angular.js”中的angular $ http服务提供了一个包装器。 So the first idea was to tell breeze to use it: 所以第一个想法是告诉微风使用它:

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

Debugging angular.js, it shows that breeze now in fact uses $http, but it does not execute the above registered interceptor. 调试angular.js,它显示breeze现在实际上使用$ http,但它不执行上面注册的拦截器。 Inside $http, there is an array "reversedInterceptors", which holds the registered interceptors. 在$ http里面,有一个数组“reversedInterceptors”,它包含已注册的拦截器。 I log this array to console. 我将此数组记录到控制台。 If i use $http, the length of this array is one (as expected), but when making request with breeze, this array is empty. 如果我使用$ http,则此数组的长度为1(如预期的那样),但在使用breeze发出请求时,此数组为空。

The question is, how can i use this $http interceptor with breeze requests? 问题是,我如何使用这个$ http拦截器与微风请求?

Here is the code for breeze.ajax.angular.js, provided by breeze 这是breeze提供的breeze.ajax.angular.js的代码

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

using the setHttp method works for me to use http interceptors with the breeze angular ajax adapter. 使用setHttp方法可以让我使用带有微风角度ajax适配器的http拦截器。 in my environment, it looks like this: 在我的环境中,它看起来像这样:

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

        ...

    }
})();

the only place I've really found any information about this is in the release notes for 1.4.4 on the download page. 我真正找到关于此的任何信息的唯一地方是在下载页面上的1.4.4发行说明中。 I don't really understand what this does. 我真的不明白这是做什么的。 i'm sure one of the breeze guys will have a better explanation. 我敢肯定其中一个微风男人会有更好的解释。

You have to call setHttp($http) as explained by @almaplayera . 您必须按setHttp($http)解释调用setHttp($http) Please mark his as the correct answer. 请将他标记为正确答案。

Here's why that is necessary. 这就是为什么这是必要的。

By default, the breeze angular ajax adapter initializes itself with whatever instance of $http is available. 默认情况下,breeze angular ajax adapter使用$ http的可用实例初始化自身。 Unfortunately, at the time that most scripts are loading, the $http instance for YOUR APP hasn't been created. 不幸的是,在加载大多数脚本时,尚未创建您的APP的$http实例。 That won't happen until your module loads ... which typically happens long after breeze loads. 在模块加载之前不会发生这种情况......通常在微风加载后很久就会发生。

So rather than create an adapter that won't work at all, breeze spins up its own instance of $http and wires the angular ajax adapter to that instance. 因此,breeze不是创建一个根本不起作用的适配器,而是旋转它自己的$http实例并将有角度的ajax适配器连接到该实例。

If your code doesn't do anything special, this works fine. 如果您的代码没有做任何特殊的事情,这可以正常工作。 It's not optimal; 这不是最佳的; you'll get one extra $digest cycle than necessary. 你将获得一个额外的$digest周期。 But it works for most people and let's admit that there is more than enough configuration noise to deal with as it is. 但它适用于大多数人,让我们承认有足够的配置噪音来处理它。

But you ARE doing something special. 但你正在做一些特别的事情。 You're configuring a very specific instance of $http , not the one that breeze created for itself. 您正在配置$http的非常具体的实例,而不是breeze为自己创建的实例。

So you have to tell breeze to use YOUR instance of $http ... and that's what happens when you call setHttp($http) ; 所以你必须告诉breeze使用你的$http实例......这就是你调用setHttp($http)时会发生的事情。

Thanks to this feedback I have updated the breeze documentation on ajax adapters to describe how to configure for an Angular app. 感谢这些反馈,我更新了ajax适配器上breeze文档,以描述如何配置Angular应用程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM