From c9c1d4095cefecce55a68cdfc7e1b45ed07a4d55 Mon Sep 17 00:00:00 2001 From: Mark Nadig Date: Wed, 30 Jan 2013 08:41:39 -0700 Subject: [PATCH] fix($resource): params should expand array values properly Today, calling e.g. var R = $resource('/Path/:a'); R.get({a: 'foo', bar: ['baz1', 'baz2']}); results in a query string like "/Path/doh?bar=baz1,baz2" which is undesirable. This commit enhances resource to use $http to encode any non-url parameters resulting in a query string like "/Path/doh?bar=baz1&bar=baz2". BREAKING CHANGE: if the server relied on the buggy behavior then either the backend should be fixed or a simple serialization of the array should be done on the client before calling the resource service. --- src/ngResource/resource.js | 15 ++++++++------- test/ngResource/resourceSpec.js | 24 ++++++++++++++++-------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/ngResource/resource.js b/src/ngResource/resource.js index 037a12ae6132..55a7b77dc144 100644 --- a/src/ngResource/resource.js +++ b/src/ngResource/resource.js @@ -303,7 +303,7 @@ angular.module('ngResource', ['ng']). } Route.prototype = { - url: function(params) { + setUrlParams: function(config, params) { var self = this, url = this.template, val, @@ -327,15 +327,16 @@ angular.module('ngResource', ['ng']). } }); url = url.replace(/\/?#$/, ''); - var query = []; + url = url.replace(/\/*$/, ''); + config.url = url; + + // delegate param encoding to $http forEach(params, function(value, key){ if (!self.urlParams[key]) { - query.push(encodeUriQuery(key) + '=' + encodeUriQuery(value)); + config.params = config.params || {}; + config.params[key] = value; } }); - query.sort(); - url = url.replace(/\/*$/, ''); - return url + (query.length ? '?' + query.join('&') : ''); } }; @@ -413,7 +414,7 @@ angular.module('ngResource', ['ng']). } }); httpConfig.data = data; - httpConfig.url = route.url(extend({}, extractParams(data, action.params || {}), params)) + route.setUrlParams(httpConfig, extend({}, extractParams(data, action.params || {}), params)); function markResolved() { value.$resolved = true; }; diff --git a/test/ngResource/resourceSpec.js b/test/ngResource/resourceSpec.js index ad9280f51c70..c827606f5253 100644 --- a/test/ngResource/resourceSpec.js +++ b/test/ngResource/resourceSpec.js @@ -118,18 +118,26 @@ describe("resource", function() { }); - it('should not encode @ in url params', function() { - //encodeURIComponent is too agressive and doesn't follow http://www.ietf.org/rfc/rfc3986.txt - //with regards to the character set (pchar) allowed in path segments - //so we need this test to make sure that we don't over-encode the params and break stuff like - //buzz api which uses @self - +// note: Waiting to hear from Igor if if this is necessary, and if so - shouldn't it be in $http instead +// it('should not encode @ in url params', function() { +// //encodeURIComponent is too agressive and doesn't follow http://www.ietf.org/rfc/rfc3986.txt +// //with regards to the character set (pchar) allowed in path segments +// //so we need this test to make sure that we don't over-encode the params and break stuff like +// //buzz api which uses @self +// +// var R = $resource('/Path/:a'); +// $httpBackend.expect('GET', '/Path/doh@fo%20o?!do%26h=g%3Da+h&:bar=$baz@1').respond('{}'); +// R.get({a: 'doh@fo o', ':bar': '$baz@1', '!do&h': 'g=a h'}); +// }); + + it('should encode array params', function() { var R = $resource('/Path/:a'); - $httpBackend.expect('GET', '/Path/doh@fo%20o?!do%26h=g%3Da+h&:bar=$baz@1').respond('{}'); - R.get({a: 'doh@fo o', ':bar': '$baz@1', '!do&h': 'g=a h'}); + $httpBackend.expect('GET', '/Path/doh&foo?bar=baz1&bar=baz2').respond('{}'); + R.get({a: 'doh&foo', bar: ['baz1', 'baz2']}); }); + it('should encode & in url params', function() { var R = $resource('/Path/:a'); $httpBackend.expect('GET', '/Path/doh&foo?bar=baz%261').respond('{}');