我希望AngularJS使用标准的javascript函数encodeURIComponent
对查询字符串参数进行编码。根据以下测试,情况并非如此:
describe('$http', function () {
it('encodes uri components correctly', inject(function($http, $httpBackend) {
var data = 'Hello from http://example.com';
$httpBackend.expectGET('/api/process?data=' + encodeURIComponent(data));
$http({ method: 'GET', url: '/api/process', params: { data: data } });
$httpBackend.flush();
}));
});
测试失败,出现以下错误:
$ http正确编码uri组件
错误:意外请求:GET /api/process?data=Hello+from+http:%2F%2Fexample.com
预期GET /api/process?data=Hello%20from%20http%3A%2F%2Fexample.com
总结一下:
Hello%20from%20http%3A%2F%2Fexample.com
Hello+from+http:%2F%2Fexample.com
对于AngularJS,我应该期待什么样的uri组件(也就是查询字符串参数)编码方法?
答案 0 :(得分:4)
Angular(至少1.3)不仅使用encodeURIComponent并更改了一些替换(例如“”to“+”)。
这是提交解释原因: https://github.com/angular/angular.js/commit/9e30baad3feafc82fb2f2011fd3f21909f4ba29e
以下是您在1.3来源中可以看到的内容:
/**
* This method is intended for encoding *key* or *value* parts of query component. We need a custom
* method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be
* encoded per http://tools.ietf.org/html/rfc3986:
* query = *( pchar / "/" / "?" )
* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
* pct-encoded = "%" HEXDIG HEXDIG
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
* / "*" / "+" / "," / ";" / "="
*/
function encodeUriQuery(val, pctEncodeSpaces) {
return encodeURIComponent(val).
replace(/%40/gi, '@').
replace(/%3A/gi, ':').
replace(/%24/g, '$').
replace(/%2C/gi, ',').
replace(/%3B/gi, ';').
replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
}
请注意,pctEncodeSpaces
已硬编码为true
;
以下是解码URI参数的方法
decodeURIComponent(val.
replace('@', '%40').
replace(':', '%3A').
replace('$', '%24').
replace(',', '%2C').
replace(';', '%3B').
replace('+', '%20'));
答案 1 :(得分:4)
在我看来,AngularJS错误地以与URI路径段和URI查询参数相同的方式进行编码。对我来说这是一个错误,我实际上发布了pull request来修复它。
我在pull请求中引入的测试实际上确认了这个bug(用AngularJS 1.3.*
和当前master
测试了它。)
答案 2 :(得分:-3)
当您传递参数pre encoding时,似乎。您编码URL但在通过JSON数据参数传递非编码的URL后。也许这对您的代码的更改将起作用。
describe('$http', function () {
it('encodes uri components correctly', inject(function($http, $httpBackend) {
var data = encodeURIComponent('Hello from http://example.com');
$httpBackend.expectGET('/api/process?data=' + encodeURIComponent(data));
$http({ method: 'GET', url: '/api/process', params: { data: data } });
$httpBackend.flush();
}));
});
此外,在仅获取URL编码片段并将其置于小提琴中之后: http://jsfiddle.net/eNtgL/1/
它似乎工作正常,您可能需要调查导致您的网址出现问题的外部因素。此处还介绍了其他几个选项