6

我期待 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
Expected 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 组件(又名查询字符串参数)编码方法?

4

3 回答 3

4

Angular(至少 1.3)不仅使用 encodeURIComponent 并且更改了一些替换项(例如“”到“+”)。

这是解释原因的提交: 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'));
于 2015-04-19T10:33:36.143 回答
4

在我看来,AngularJS 以与 URI 路径段和 URI 查询参数相同的方式错误地编码。对我来说这是一个错误,我实际上发出了修复它的请求请求

我在拉取请求中引入的测试实际上证实了这个错误(用 AngularJS1.3.*和 current测试它master)。

于 2015-06-24T10:08:54.637 回答
-3

看来,当您传递参数预编码时。您对 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/

它似乎工作正常,您可能需要调查导致您的 URL 出现问题的外部因素。这里还描述了其他几个选项

在 JavaScript 中编码 URL?

于 2014-07-02T23:31:16.917 回答