javascript AngularJS 资源:如何禁用 url 实体编码
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22944932/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
AngularJS resource: how to disable url entity encoding
提问by polyclick
On my current project I have a drupal backend that exposes rest services for my frontend. Some calls to my backend don't really like url entities to get encoded.
在我当前的项目中,我有一个 drupal 后端,它为我的前端公开休息服务。对我的后端的一些调用并不真正喜欢对 url 实体进行编码。
So my question is: how do I disable URL encoding of some parameters?
所以我的问题是:如何禁用某些参数的 URL 编码?
Example:
例子:
I need to call my backend with a "+"-sign between different search terms. Like so:
我需要在不同的搜索词之间使用“+”号来调用我的后端。像这样:
http://backend.com/someservice/search/?terms=search+terms+here
But angular, setup like so:
但是有角度的,设置如下:
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});
};
Calls the following url:
调用以下网址:
http://backend.com/someservice/search/?terms=search%2Bterms%2Bhere
Any suggestions? Thanks!
有什么建议?谢谢!
采纳答案by Pieter Herroelen
Update: with the new httpParamSerializerin Angular 1.4 you can do it by writing your own paramSerializer and setting $httpProvider.defaults.paramSerializer
.
更新:使用Angular 1.4 中的新httpParamSerializer,您可以通过编写自己的 paramSerializer 并设置$httpProvider.defaults.paramSerializer
.
Below only applies to AngularJS 1.3 (and older).
以下仅适用于 AngularJS 1.3(及更早版本)。
It is not possible without changing the source of AngularJS.
不改变 AngularJS 的源代码是不可能的。
This is done by $http:
这是由 $http 完成的:
https://github.com/angular/angular.js/tree/v1.3.0-rc.5/src/ng/http.js#L1057
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
uses the standard encodeUriComponent
(MDN) which replaces the '+' with '%2B'
encodeUriQuery
使用标准encodeUriComponent
( MDN) 将 '+' 替换为 '%2B'
Too bad you cannot overwrite encodeUriQuery
because it is a local variable inside the angular function.
太糟糕了,您无法覆盖,encodeUriQuery
因为它是 angular 函数内的局部变量。
So the only option I see is to overwrite window.encodeURIComponent
. I've done it in an $http interceptor to minimize the impact. Note that the original function is only put back when the response comes back, so this change is global (!!) while your request is ongoing. So be sure to test if this doesn't break something else in your application.
所以我看到的唯一选择是覆盖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);
}
};
});
});
回答by mer10z_tech
AngularJS only runs the encodeUriQuery method if you pass your params as an extra object. If you manually create your own param string and concatenate it onto your URL then Angular won't modify it.
如果您将参数作为额外对象传递,AngularJS 只会运行 encodeUriQuery 方法。如果您手动创建自己的参数字符串并将其连接到您的 URL 上,那么 Angular 将不会修改它。
It's pretty simple to convert the param object yourself, here's an example: How to serialize an Object into a list of parameters?
自己转换 param 对象非常简单,这里有一个例子:如何将一个 Object 序列化为一个参数列表?
回答by Antonio E.
While usually you don't want to do it (since on server side you can decode the request URI with a URL decode function to get back your plus signes) sometimes we want to "break" the rules.
虽然通常您不想这样做(因为在服务器端您可以使用 URL 解码功能解码请求 URI 以取回您的加号),但有时我们想要“打破”规则。
Right now I can't actually test it (it would be helpful if you can create a jsfiddle with a test case for us to play with) but probably you should take a look at the transformRequest function of the resource object.
现在我无法实际测试它(如果您可以创建一个带有测试用例的 jsfiddle 供我们使用,那将会很有帮助)但您可能应该看看资源对象的transformRequest 函数。
From the docs:
从文档:
transformRequest – {function(data, headersGetter)|Array.} – transform function or an array of such functions. The transform function takes the http request body and headers and returns its transformed (typically serialized) version.
transformRequest – {function(data, headersGetter)|Array.} – 转换函数或此类函数的数组。转换函数采用 http 请求正文和标头并返回其转换后的(通常是序列化的)版本。
回答by Jim Schubert
It looks like the $resource
code wraps this functionality in Route.prototype.setUrlParams
:
看起来$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;
}
});
}
});
And it looks like the resourceFactory
function creates a closure over the constructed route, so you don't have access to change this.
看起来该resourceFactory
函数在构造的路由上创建了一个闭包,因此您无权更改它。
Do you specifically need this to be a resource object? If not, you can create a plain $http
call and use a request transform as Antonio mentioned.
您是否特别需要将其作为资源对象?如果没有,您可以创建一个简单的$http
调用并使用安东尼奥提到的请求转换。