是否可以使用Angular的$ http服务指定参数顺序?

时间:2014-11-25 15:44:34

标签: angularjs angularjs-http

在我的Angular应用程序中,我有一个利用$http从服务器检索数据的服务。服务器端点使用HMAC身份验证,并期望查询字符串参数在URL上按特定顺序排列。

Angular sorts the $http parameters when it builds the URL,因此似乎无法指定自定义参数顺序。

以下是一个例子:

this.apiCall = function() {
    return $http({
        method: 'GET',
        url: 'http://example.com/url/v1/endpoint',
        params: {
            'c': 'cdata',
            'a': 'adata',
            'b': 'bdata'
        }
    });
};

Angular会将网址构建为http://example.com/url/v1/endpoint?a=adata&b=bdata&c=cdata,但我需要按照指定http://example.com/url/v1/endpoint?c=cdata&a=adata&b=bdata保留参数的顺序。

我意识到我可以手动修改URL字符串的参数,但这不是很友好,并且不允许在$http拦截器中轻松管理。

Angular可能会对参数进行排序,以便在浏览器实现中保持统一的行为,因为ECMAScript中未指定对象排序。

无论如何,是否有人知道如何解决对params进行排序的默认Angular行为,以便构建一个保留指定参数的URL?

2 个答案:

答案 0 :(得分:3)

我改进了您的解决方案,以创建更流线型并确保工作的内容:

$httpProvider.interceptors.push(function() {
    return {
        request: function (config) {
            if (!config.paramOrder) {
                return config;
            }

            // avoid leaking config modifications
            config = angular.copy(config, {});

            var orderedParams = [];
            config.paramOrder.forEach(function (key) {
                if (config.params.hasOwnProperty(key)) {
                    orderedParams.push(encodeURIComponent(key) + '=' + encodeURIComponent(config.params[key]));
                    // leave only the unordered params in the `params` config
                    delete config.params[key];
                }
            });

            config.url += (config.url.indexOf('?') === -1) ? '?' : '&';
            config.url += orderedParams.join('&');

            return config;
        },
    };
});

使用以下内容调用:

$http({
    method: 'GET',
    url: 'http://example.com/url/v1/endpoint',
    params: {
        a: 'aValue',
        b: 'bValue',
        c: 'cValue'
    },
    paramOrder: ['c', 'a']
});

获取以密钥c开头,后跟a的查询字符串。 paramOrder中未提及的参数将附加在有序参数之后(按字母顺序排列)。

答案 1 :(得分:1)

我最终创建了一个基本的拦截器来保持" as-specified" params命令。如果在keepParamsOrder调用上设置了$http配置变量,则会运行此拦截器。

在你的模块配置中:

$httpProvider.interceptors.push(function() {
    return {
        'request': function(config) {
            if (!config.keepParamsOrder || !config.params) {
                return config;
            }

            var queryStrings = [];
            for (var key in config.params) {
                if (config.params.hasOwnProperty(key)) {
                    queryStrings.push(key + '=' + config.params[key]);
                }
            }

            // Reset the params to be empty
            config.params = {};

            config.url += (config.url.indexOf('?') === -1) ? '?' : '&';
            config.url += queryStrings.join('&');

            return config;
        },
    };
});

告诉它在服务调用配置中运行:

this.apiCall = function() {
    return $http({
        method: 'GET',
        url: 'http://example.com/url/v1/endpoint',
        params: {
            'c': 'cdata',
            'a': 'adata',
            'b': 'bdata'
        },
        keepParamsOrder: true
    });
};