@@ -9,6 +9,64 @@ var JSON_ENDS = {
99} ;
1010var JSON_PROTECTION_PREFIX = / ^ \) \] \} ' , ? \n / ;
1111
12+ function paramSerializerFactory ( jQueryMode ) {
13+
14+ function serializeValue ( v ) {
15+ if ( isObject ( v ) ) {
16+ return isDate ( v ) ? v . toISOString ( ) : toJson ( v ) ;
17+ }
18+ return v ;
19+ }
20+
21+ return function paramSerializer ( params ) {
22+ if ( ! params ) return '' ;
23+ var parts = [ ] ;
24+ forEachSorted ( params , function ( value , key ) {
25+ if ( value === null || isUndefined ( value ) ) return ;
26+ if ( isArray ( value ) || isObject ( value ) && jQueryMode ) {
27+ forEach ( value , function ( v , k ) {
28+ var keySuffix = jQueryMode ? '[' + ( ! isArray ( value ) ? k : '' ) + ']' : '' ;
29+ parts . push ( encodeUriQuery ( key ) + keySuffix + '=' + encodeUriQuery ( serializeValue ( v ) ) ) ;
30+ } ) ;
31+ } else {
32+ parts . push ( encodeUriQuery ( key ) + '=' + encodeUriQuery ( serializeValue ( value ) ) ) ;
33+ }
34+ } ) ;
35+
36+ return parts . length > 0 ? parts . join ( '&' ) : '' ;
37+ } ;
38+ }
39+
40+ /**
41+ * @ngdoc provider
42+ * @name $HttpParamSerializerProvider
43+ * @description
44+ *
45+ * Default $http params serializer that converts objects to a part of a request URL
46+ * according to the following rules:
47+ * * `{'foo': 'bar'}` results in `foo=bar`
48+ * * `{'foo': Date.now()}` results in `foo=2015-04-01T09%3A50%3A49.262Z` (`toISOString()` and encoded representation of a Date object)
49+ * * `{'foo': ['bar', 'baz']}` results in `foo=bar&foo=baz` (repeated key for each array element)
50+ * * `{'foo': {'bar':'baz'}}` results in `foo=%7B%22bar%22%3A%22baz%22%7D"` (stringified and encoded representation of an object)
51+ * */
52+ function $HttpParamSerializerProvider ( ) {
53+ this . $get = function ( ) {
54+ return paramSerializerFactory ( false ) ;
55+ } ;
56+ }
57+
58+ /**
59+ * @ngdoc provider
60+ * @name $HttpParamSerializerJQLikeProvider
61+ *
62+ * Alternative $http params serializer that follows jQuerys `param()` method {http://api.jquery.com/jquery.param/} logic.
63+ * */
64+ function $HttpParamSerializerJQLikeProvider ( ) {
65+ this . $get = function ( ) {
66+ return paramSerializerFactory ( true ) ;
67+ } ;
68+ }
69+
1270function defaultHttpResponseTransform ( data , headers ) {
1371 if ( isString ( data ) ) {
1472 // Strip json vulnerability protection prefix and trim whitespace
@@ -153,6 +211,11 @@ function $HttpProvider() {
153211 * - **`defaults.headers.put`**
154212 * - **`defaults.headers.patch`**
155213 *
214+ * - **`defaults.paramSerializer`** - {string|function([paramsObject])} - A function used to prepare string representation
215+ * of request parameters (specified as an object).
216+ * Is specified as string, it is interpreted as function registered in with the {$injector}.
217+ * Defaults to {$httpParamSerializer}.
218+ *
156219 **/
157220 var defaults = this . defaults = {
158221 // transform incoming response data
@@ -174,7 +237,9 @@ function $HttpProvider() {
174237 } ,
175238
176239 xsrfCookieName : 'XSRF-TOKEN' ,
177- xsrfHeaderName : 'X-XSRF-TOKEN'
240+ xsrfHeaderName : 'X-XSRF-TOKEN' ,
241+
242+ paramSerializer : '$httpParamSerializer'
178243 } ;
179244
180245 var useApplyAsync = false ;
@@ -188,7 +253,7 @@ function $HttpProvider() {
188253 * significant performance improvement for bigger applications that make many HTTP requests
189254 * concurrently (common during application bootstrap).
190255 *
191- * Defaults to false. If no value is specifed , returns the current configured value.
256+ * Defaults to false. If no value is specified , returns the current configured value.
192257 *
193258 * @param {boolean= } value If true, when requests are loaded, they will schedule a deferred
194259 * "apply" on the next tick, giving time for subsequent requests in a roughly ~10ms window
@@ -225,6 +290,12 @@ function $HttpProvider() {
225290
226291 var defaultCache = $cacheFactory ( '$http' ) ;
227292
293+ /**
294+ * Make sure that default param serializer is exposed as a function
295+ */
296+ defaults . paramSerializer = isString ( defaults . paramSerializer ) ?
297+ $injector . get ( defaults . paramSerializer ) : defaults . paramSerializer ;
298+
228299 /**
229300 * Interceptors stored in reverse order. Inner interceptors before outer interceptors.
230301 * The reversal is needed so that we can build up the interception chain around the
@@ -636,6 +707,9 @@ function $HttpProvider() {
636707 * response body, headers and status and returns its transformed (typically deserialized) version.
637708 * See {@link ng.$http#overriding-the-default-transformations-per-request
638709 * Overriding the Default Transformations}
710+ * - **paramSerializer** - {string|function([paramsObject])} - A function used to prepare string representation
711+ * of request parameters (specified as an object).
712+ * Is specified as string, it is interpreted as function registered in with the {$injector}.
639713 * - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the
640714 * GET request, otherwise if a cache instance built with
641715 * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for
@@ -764,11 +838,14 @@ function $HttpProvider() {
764838 var config = extend ( {
765839 method : 'get' ,
766840 transformRequest : defaults . transformRequest ,
767- transformResponse : defaults . transformResponse
841+ transformResponse : defaults . transformResponse ,
842+ paramSerializer : defaults . paramSerializer
768843 } , requestConfig ) ;
769844
770845 config . headers = mergeHeaders ( requestConfig ) ;
771846 config . method = uppercase ( config . method ) ;
847+ config . paramSerializer = isString ( config . paramSerializer ) ?
848+ $injector . get ( config . paramSerializer ) : config . paramSerializer ;
772849
773850 var serverRequest = function ( config ) {
774851 var headers = config . headers ;
@@ -1032,7 +1109,7 @@ function $HttpProvider() {
10321109 cache ,
10331110 cachedResp ,
10341111 reqHeaders = config . headers ,
1035- url = buildUrl ( config . url , config . params ) ;
1112+ url = buildUrl ( config . url , config . paramSerializer ( config . params ) ) ;
10361113
10371114 $http . pendingRequests . push ( config ) ;
10381115 promise . then ( removePendingReq , removePendingReq ) ;
@@ -1139,27 +1216,9 @@ function $HttpProvider() {
11391216 }
11401217
11411218
1142- function buildUrl ( url , params ) {
1143- if ( ! params ) return url ;
1144- var parts = [ ] ;
1145- forEachSorted ( params , function ( value , key ) {
1146- if ( value === null || isUndefined ( value ) ) return ;
1147- if ( ! isArray ( value ) ) value = [ value ] ;
1148-
1149- forEach ( value , function ( v ) {
1150- if ( isObject ( v ) ) {
1151- if ( isDate ( v ) ) {
1152- v = v . toISOString ( ) ;
1153- } else {
1154- v = toJson ( v ) ;
1155- }
1156- }
1157- parts . push ( encodeUriQuery ( key ) + '=' +
1158- encodeUriQuery ( v ) ) ;
1159- } ) ;
1160- } ) ;
1161- if ( parts . length > 0 ) {
1162- url += ( ( url . indexOf ( '?' ) == - 1 ) ? '?' : '&' ) + parts . join ( '&' ) ;
1219+ function buildUrl ( url , serializedParams ) {
1220+ if ( serializedParams . length > 0 ) {
1221+ url += ( ( url . indexOf ( '?' ) == - 1 ) ? '?' : '&' ) + serializedParams ;
11631222 }
11641223 return url ;
11651224 }
0 commit comments