diff --git a/src/service/http.js b/src/service/http.js index 17cc68ea0e51..c2cbd16174a3 100644 --- a/src/service/http.js +++ b/src/service/http.js @@ -1,4 +1,5 @@ 'use strict'; +'use strict'; /** * Parse headers into key value object @@ -360,6 +361,8 @@ function $HttpProvider() { * * - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc) * - **url** – `{string}` – Absolute or relative URL of the resource that is being requested. + * - **params** – `{Object.}` – Map of strings or objects which will be turned to + * `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified. * - **data** – `{string|Object}` – Data to be sent as the request message data. * - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server. * - **transformRequest** – `{function(data, headersGetter)|Array.}` – @@ -638,7 +641,8 @@ function $HttpProvider() { var deferred = $q.defer(), promise = deferred.promise, cache, - cachedResp; + cachedResp, + url = buildUrl(config.url, config.params); $http.pendingRequests.push(config); promise.then(removePendingReq, removePendingReq); @@ -649,7 +653,7 @@ function $HttpProvider() { } if (cache) { - cachedResp = cache.get(config.url); + cachedResp = cache.get(url); if (cachedResp) { if (cachedResp.then) { // cached request has already been sent, but there is no response yet @@ -665,13 +669,13 @@ function $HttpProvider() { } } else { // put the promise for the non-transformed response into cache as a placeholder - cache.put(config.url, promise); + cache.put(url, promise); } } // if we won't have the response in cache, send the request to the backend if (!cachedResp) { - $httpBackend(config.method, config.url, reqData, done, reqHeaders, config.timeout); + $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout); } return promise; @@ -686,10 +690,10 @@ function $HttpProvider() { function done(status, response, headersString) { if (cache) { if (isSuccess(status)) { - cache.put(config.url, [status, response, parseHeaders(headersString)]); + cache.put(url, [status, response, parseHeaders(headersString)]); } else { // remove promise from the cache - cache.remove(config.url); + cache.remove(url); } } @@ -719,5 +723,21 @@ function $HttpProvider() { if (idx !== -1) $http.pendingRequests.splice(idx, 1); } } + + + function buildUrl(url, params) { + if (!params) return url; + var parts = []; + forEachSorted(params, function(value, key) { + if (value == null || value == undefined) return; + if (isObject(value)) { + value = toJson(value); + } + parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value)); + }); + return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&'); + } + + }]; } diff --git a/test/service/httpSpec.js b/test/service/httpSpec.js index 43dbf3aff055..ab50827c2272 100644 --- a/test/service/httpSpec.js +++ b/test/service/httpSpec.js @@ -132,6 +132,26 @@ describe('$http', function() { // TODO(vojta): test passing timeout + describe('params', function() { + it('should do basic request with params and encode', inject(function($httpBackend, $http) { + $httpBackend.expect('GET', '/url?a%3D=%3F%26&b=2').respond(''); + $http({url: '/url', params: {'a=':'?&', b:2}, method: 'GET'}); + })); + + + it('should merge params if url contains some already', inject(function($httpBackend, $http) { + $httpBackend.expect('GET', '/url?c=3&a=1&b=2').respond(''); + $http({url: '/url?c=3', params: {a:1, b:2}, method: 'GET'}); + })); + + + it('should jsonify objects in params map', inject(function($httpBackend, $http) { + $httpBackend.expect('GET', '/url?a=1&b=%7B%22c%22%3A3%7D').respond(''); + $http({url: '/url', params: {a:1, b:{c:3}}, method: 'GET'}); + })); + }); + + describe('callbacks', function() { it('should pass in the response object when a request is successful', function() {