在我的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?
答案 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
});
};