Skip to content

Commit 16b3a33

Browse files
feat($httpUrlParams): introduce new service abstracting params serialization
Closes angular#7429 Closes angular#9224
1 parent 0c541cf commit 16b3a33

File tree

2 files changed

+83
-24
lines changed

2 files changed

+83
-24
lines changed

src/AngularPublic.js

+2
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
$IntervalProvider,
6868
$HttpProvider,
6969
$HttpBackendProvider,
70+
$HttpUrlParamsProvider,
7071
$LocationProvider,
7172
$LogProvider,
7273
$ParseProvider,
@@ -224,6 +225,7 @@ function publishExternalAPI(angular) {
224225
$interval: $IntervalProvider,
225226
$http: $HttpProvider,
226227
$httpBackend: $HttpBackendProvider,
228+
$httpUrlParams: $HttpUrlParamsProvider,
227229
$location: $LocationProvider,
228230
$log: $LogProvider,
229231
$parse: $ParseProvider,

src/ng/http.js

+81-24
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,8 @@ function $HttpProvider() {
220220
**/
221221
var interceptorFactories = this.interceptors = [];
222222

223-
this.$get = ['$httpBackend', '$$cookieReader', '$cacheFactory', '$rootScope', '$q', '$injector',
224-
function($httpBackend, $$cookieReader, $cacheFactory, $rootScope, $q, $injector) {
223+
this.$get = ['$httpBackend', '$httpUrlParams', '$$cookieReader', '$cacheFactory', '$rootScope', '$q', '$injector',
224+
function($httpBackend, $httpUrlParams, $$cookieReader, $cacheFactory, $rootScope, $q, $injector) {
225225

226226
var defaultCache = $cacheFactory('$http');
227227

@@ -1028,7 +1028,7 @@ function $HttpProvider() {
10281028
cache,
10291029
cachedResp,
10301030
reqHeaders = config.headers,
1031-
url = buildUrl(config.url, config.params);
1031+
url = buildUrl(config.url, config.params, config.paramsMode);
10321032

10331033
$http.pendingRequests.push(config);
10341034
promise.then(removePendingReq, removePendingReq);
@@ -1135,29 +1135,86 @@ function $HttpProvider() {
11351135
}
11361136

11371137

1138-
function buildUrl(url, params) {
1139-
if (!params) return url;
1140-
var parts = [];
1141-
forEachSorted(params, function(value, key) {
1142-
if (value === null || isUndefined(value)) return;
1143-
if (!isArray(value)) value = [value];
1144-
1145-
forEach(value, function(v) {
1146-
if (isObject(v)) {
1147-
if (isDate(v)) {
1148-
v = v.toISOString();
1149-
} else {
1150-
v = toJson(v);
1151-
}
1152-
}
1153-
parts.push(encodeUriQuery(key) + '=' +
1154-
encodeUriQuery(v));
1155-
});
1156-
});
1157-
if (parts.length > 0) {
1158-
url += ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');
1138+
function buildUrl(url, params, mode) {
1139+
params = $httpUrlParams.serialize(params, mode);
1140+
if (params) {
1141+
url += ((url.indexOf('?') == -1) ? '?' : '&') + params;
11591142
}
11601143
return url;
11611144
}
11621145
}];
11631146
}
1147+
1148+
/**
1149+
* @ngdoc provider
1150+
* @name $httpUrlParamsProvider
1151+
* @description
1152+
* Use `$httpUrlParamsProvider` to change the default behavior of the {@link ng.$httpUrlParams $httpUrlParams} service.
1153+
* */
1154+
function $HttpUrlParamsProvider() {
1155+
1156+
var paramSerializers = createMap();
1157+
1158+
function serializeParams(params, addArrayMarker) {
1159+
var parts = [];
1160+
1161+
if (!params) return '';
1162+
1163+
forEachSorted(params, function(value, key) {
1164+
if (value === null || isUndefined(value)) return;
1165+
if (!isArray(value)) value = [value];
1166+
1167+
forEach(value, function(v) {
1168+
if (isObject(v)) {
1169+
v = isDate(v) ? v.toISOString() : toJson(v);
1170+
}
1171+
parts.push(encodeUriQuery(key) + (addArrayMarker ? '[]' : '') + '=' + encodeUriQuery(v));
1172+
});
1173+
});
1174+
1175+
return parts.join('&');
1176+
}
1177+
1178+
1179+
this.defaultMode = 'traditional';
1180+
1181+
1182+
this.registerSerializer = function registerSerializer(mode, serFn) {
1183+
paramSerializers[mode] = serFn;
1184+
};
1185+
1186+
/**
1187+
* @ngdoc service
1188+
* @name $httpUrlParams
1189+
*
1190+
* @description
1191+
* The `$httpUrlParams` service is responsible for serializing request params
1192+
* (expressed as a JavaScript object) to a string.
1193+
* It abstracts the way in which request params are transformed, grouped, encoded etc.
1194+
*
1195+
* Normally you wouldn't use this service directly in the application's code but rather override this service
1196+
* to enable custom serialization schemas for URL parameters.
1197+
*
1198+
* The `$httpUrlParams` service comes handy while unit testing with {@link ngMock.$httpBackend $httpBackend mock},
1199+
* as one can inject `$httpUrlParams` into a test and serialize URL params as {@link ng.$http $http} service.
1200+
*/
1201+
this.$get = function() {
1202+
1203+
var provider = this;
1204+
var HttpUrlParams = {};
1205+
1206+
HttpUrlParams.serialize = function(params, mode) {
1207+
return paramSerializers[lowercase(mode) || provider.defaultMode](params);
1208+
};
1209+
1210+
return HttpUrlParams;
1211+
};
1212+
1213+
this.registerSerializer(this.defaultMode, function(params) {
1214+
return serializeParams(params, false);
1215+
});
1216+
1217+
this.registerSerializer('jquery', function(params) {
1218+
return serializeParams(params, false);
1219+
});
1220+
}

0 commit comments

Comments
 (0)