在我目前的项目中,我有一个drupal后端,为我的前端公开了休息服务。 对我的后端的一些调用并不像url实体那样被编码。
所以我的问题是:如何禁用某些参数的URL编码?
示例:
我需要在不同的搜索字词之间用“+”标记我的后端。像这样:
http://backend.com/someservice/search/?terms=search+terms+here
但角度,设置如下:
var resource = $resource(
backendUrl + '/views/:view', {},
{
'search': {params:{view:'searchposts'}, isArray:true}
}
);
// search posts for the given terms
this.searchPosts = function(terms, limit) {
resource.search({search:terms.join('+'), limit:limit});
};
调用以下网址:
http://backend.com/someservice/search/?terms=search%2Bterms%2Bhere
有什么建议吗?谢谢!
答案 0 :(得分:9)
更新:使用Angular 1.4中的新httpParamSerializer,您可以编写自己的paramSerializer并设置$httpProvider.defaults.paramSerializer
。
以下仅适用于AngularJS 1.3(及更早版本)。
如果不改变AngularJS的来源是不可能的。
这是由$ http:
完成的https://github.com/angular/angular.js/tree/v1.3.0-rc.5/src/ng/http.js#L1057
function buildUrl(url, params) {
if (!params) return url;
var parts = [];
forEachSorted(params, function(value, key) {
if (value === null || isUndefined(value)) return;
if (!isArray(value)) value = [value];
forEach(value, function(v) {
if (isObject(v)) {
v = toJson(v);
}
parts.push(encodeUriQuery(key) + '=' +
encodeUriQuery(v));
});
});
if(parts.length > 0) {
url += ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');
}
return url;
}
encodeUriQuery
使用标准encodeUriComponent
(MDN)将'+'替换为'%2B'
太糟糕了,你无法覆盖encodeUriQuery
,因为它是角度函数中的局部变量。
所以我看到的唯一选择是覆盖window.encodeURIComponent
。我已经在$ http拦截器中完成了它,以尽量减少影响。请注意,原始功能仅在响应返回时放回,因此在您的请求正在进行时,此更改是全局的(!!)。因此,请务必测试这是否会破坏您应用程序中的其他内容。
app.config(function($httpProvider) {
$httpProvider.interceptors.push(function($q) {
var realEncodeURIComponent = window.encodeURIComponent;
return {
'request': function(config) {
window.encodeURIComponent = function(input) {
return realEncodeURIComponent(input).split("%2B").join("+");
};
return config || $q.when(config);
},
'response': function(config) {
window.encodeURIComponent = realEncodeURIComponent;
return config || $q.when(config);
}
};
});
});
答案 1 :(得分:4)
如果将params作为额外对象传递,AngularJS仅运行encodeUriQuery方法。如果你手动创建自己的param字符串并将其连接到你的URL上,那么Angular不会修改它。
自己转换param对象非常简单,例如:How to serialize an Object into a list of parameters?
答案 2 :(得分:0)
虽然通常你不想这样做(因为在服务器端你可以使用URL解码函数解码请求URI以取回你的加号)有时候我们想要“破坏”规则。
现在我无法对它进行实际测试(如果您可以为我们创建一个带有测试用例的jsfiddle,那会很有帮助)但是您可能应该看一下transformRequest function of the resource object。
来自文档:
transformRequest - {function(data,data, headersGetter)| Array。} - transform 函数或这些函数的数组。转换函数需要 http请求正文和标题并返回其转换后的内容 (通常是序列化的)版本。
答案 3 :(得分:0)
看起来$resource
代码在Route.prototype.setUrlParams
中包含了此功能:
params = params || {};
forEach(self.urlParams, function (_, urlParam) {
val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];
if (angular.isDefined(val) && val !== null) {
encodedVal = encodeUriSegment(val);
url = url.replace(new RegExp(":" + urlParam + "(\\W|$)", "g"), function (match, p1) {
return encodedVal + p1;
});
} else {
url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W|$)", "g"), function (match,
leadingSlashes, tail) {
if (tail.charAt(0) == '/') {
return tail;
} else {
return leadingSlashes + tail;
}
});
}
});
看起来resourceFactory
函数会在构造的路径上创建一个闭包,因此您无权更改此内容。
您是否特别需要将其作为资源对象?如果没有,您可以创建一个简单的$http
调用并使用Antonio提到的请求转换。