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.
This commit is contained in:
Mark Nadig 2013-01-30 08:41:39 -07:00 committed by Vojta Jina
parent 1d7a95df56
commit 2a2123441c
2 changed files with 27 additions and 17 deletions

View file

@ -316,7 +316,7 @@ angular.module('ngResource', ['ng']).
}
Route.prototype = {
url: function(params) {
setUrlParams: function(config, params) {
var self = this,
url = this.template,
val,
@ -339,16 +339,17 @@ angular.module('ngResource', ['ng']).
});
}
});
url = url.replace(/\/?#$/, '');
var query = [];
// set the url
config.url = url.replace(/\/?#$/, '').replace(/\/*$/, '');
// set params - 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('&') : '');
}
};
@ -426,7 +427,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; }

View file

@ -118,15 +118,24 @@ 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
// In order to get this passed, we need to fix $http - another breaking change,
// so I'm gonna submit that as a separate CL.
xit('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 allow relative paths in resource url', function () {
@ -554,7 +563,7 @@ describe("resource", function() {
expect(response).toEqualData({
data: [{id: 1}, {id :2}],
status: 200,
config: {method: 'GET', data: undefined, url: '/CreditCard?key=value'},
config: {method: 'GET', data: undefined, url: '/CreditCard', params: {key: 'value'}},
resource: [ { id : 1 }, { id : 2 } ]
});
expect(typeof response.resource[0].$save).toBe('function');
@ -603,7 +612,7 @@ describe("resource", function() {
expect(response).toEqualData({
data : 'resource not found',
status : 404,
config : { method : 'GET', data : undefined, url : '/CreditCard?key=value' }
config : { method : 'GET', data : undefined, url : '/CreditCard', params: {key: 'value'}}
});
});