2
0
mirror of https://github.com/tenrok/axios.git synced 2026-05-15 11:59:42 +03:00

URL params serializer; (#4734)

* Refactored BuildURL helper to use URLSearchParams serializer;

* Updated typings;
Added TS test;
This commit is contained in:
Dmitriy Mozgovoy
2022-05-25 09:16:38 +03:00
committed by GitHub
parent 467025bdb7
commit 934f390cc3
7 changed files with 84 additions and 87 deletions
Vendored
+17 -5
View File
@@ -90,22 +90,34 @@ export interface GenericAbortSignal {
}
export interface FormDataVisitorHelpers {
defaultVisitor: FormDataVisitor;
defaultVisitor: SerializerVisitor;
convertValue: (value: any) => any;
isVisitable: (value: any) => boolean;
}
export interface FormDataVisitor {
export interface SerializerVisitor {
(value: any, key: string | number, path: null | Array<string | number>, helpers: FormDataVisitorHelpers): boolean;
}
export interface FormSerializerOptions {
visitor?: FormDataVisitor;
export interface SerializerOptions {
visitor?: SerializerVisitor;
dots?: boolean;
metaTokens?: boolean;
indexes?: boolean;
}
// tslint:disable-next-line
export interface FormSerializerOptions extends SerializerOptions {
}
export interface ParamEncoder {
(value: any, defaultEncoder: (value: any) => any): any;
}
export interface ParamsSerializerOptions extends SerializerOptions {
encode?: ParamEncoder;
}
export interface AxiosRequestConfig<D = any> {
url?: string;
method?: Method | string;
@@ -114,7 +126,7 @@ export interface AxiosRequestConfig<D = any> {
transformResponse?: AxiosResponseTransformer | AxiosResponseTransformer[];
headers?: AxiosRequestHeaders;
params?: any;
paramsSerializer?: (params: any) => string;
paramsSerializer?: ParamsSerializerOptions;
data?: D;
timeout?: number;
timeoutErrorMessage?: string;
+42
View File
@@ -0,0 +1,42 @@
'use strict';
var toFormData = require('./toFormData');
function encode(str) {
var charMap = {
'!': '%21',
"'": '%27',
'(': '%28',
')': '%29',
'~': '%7E',
'%20': '+',
'%00': '\x00'
};
return encodeURIComponent(str).replace(/[!'\(\)~]|%20|%00/g, function replacer(match) {
return charMap[match];
});
}
function AxiosURLSearchParams(params, options) {
this._pairs = [];
params && toFormData(params, this, options);
}
var prototype = AxiosURLSearchParams.prototype;
prototype.append = function append(name, value) {
this._pairs.push([name, value]);
};
prototype.toString = function toString(encoder) {
var _encode = encoder ? function(value) {
return encoder.call(this, value, encode);
} : encode;
return this._pairs.map(function each(pair) {
return _encode(pair[0]) + '=' + _encode(pair[1]);
}, '').join('&');
};
module.exports = AxiosURLSearchParams;
+14 -38
View File
@@ -1,6 +1,7 @@
'use strict';
var utils = require('./../utils');
var utils = require('../utils');
var AxiosURLSearchParams = require('../helpers/AxiosURLSearchParams');
function encode(val) {
return encodeURIComponent(val).
@@ -17,54 +18,29 @@ function encode(val) {
*
* @param {string} url The base of the url (e.g., http://www.google.com)
* @param {object} [params] The params to be appended
* @param {?object} paramsSerializer
* @param {?object} options
* @returns {string} The formatted url
*/
module.exports = function buildURL(url, params, paramsSerializer) {
module.exports = function buildURL(url, params, options) {
/*eslint no-param-reassign:0*/
if (!params) {
return url;
}
var serializedParams;
if (paramsSerializer) {
serializedParams = paramsSerializer(params);
} else if (utils.isURLSearchParams(params)) {
serializedParams = params.toString();
} else {
var parts = [];
var hashmarkIndex = url.indexOf('#');
utils.forEach(params, function serialize(val, key) {
if (val === null || typeof val === 'undefined') {
return;
}
if (utils.isArray(val)) {
key = key + '[]';
} else {
val = [val];
}
utils.forEach(val, function parseValue(v) {
if (utils.isDate(v)) {
v = v.toISOString();
} else if (utils.isObject(v)) {
v = JSON.stringify(v);
}
parts.push(encode(key) + '=' + encode(v));
});
});
serializedParams = parts.join('&');
if (hashmarkIndex !== -1) {
url = url.slice(0, hashmarkIndex);
}
if (serializedParams) {
var hashmarkIndex = url.indexOf('#');
if (hashmarkIndex !== -1) {
url = url.slice(0, hashmarkIndex);
}
var _encode = options && options.encode || encode;
url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams;
var serializerParams = utils.isURLSearchParams(params) ?
params.toString() :
new AxiosURLSearchParams(params, options).toString(_encode);
if (serializerParams) {
url += (url.indexOf('?') === -1 ? '?' : '&') + serializerParams;
}
return url;
+4
View File
@@ -46,6 +46,10 @@ function isSpecCompliant(thing) {
**/
function toFormData(obj, formData, options) {
if (!utils.isObject(obj)) {
throw new TypeError('target must be an object');
}
// eslint-disable-next-line no-param-reassign
formData = formData || new (envFormData || FormData)();
@@ -1,36 +1,5 @@
'use strict';
module.exports = typeof URLSearchParams !== 'undefined' ? URLSearchParams : (function defineURLSearchParams() {
function encode(str) {
var charMap = {
'!': '%21',
"'": '%27',
'(': '%28',
')': '%29',
'~': '%7E',
'%20': '+',
'%00': '\x00'
};
return encodeURIComponent(str).replace(/[!'\(\)~]|%20|%00/g, function replacer(match) {
return charMap[match];
});
}
var AxiosURLSearchParams = require('../../../helpers/AxiosURLSearchParams');
function URLSearchParams() {
this.pairs = [];
}
var prototype = URLSearchParams.prototype;
prototype.append = function append(name, value) {
this.pairs.push([name, value]);
};
prototype.toString = function toString() {
return this.pairs.map(function each(pair) {
return pair[0] + '=' + encode(pair[1]);
}, '').join('&');
};
return URLSearchParams;
})();
module.exports = typeof URLSearchParams !== 'undefined' ? URLSearchParams : AxiosURLSearchParams;
+1 -10
View File
@@ -17,7 +17,7 @@ describe('helpers::buildURL', function () {
foo: {
bar: 'baz'
}
})).toEqual('/foo?foo=' + encodeURI('{"bar":"baz"}'));
})).toEqual('/foo?foo[bar]=baz');
});
it('should support date params', function () {
@@ -60,15 +60,6 @@ describe('helpers::buildURL', function () {
})).toEqual('/foo?foo=bar&query=baz');
});
it('should use serializer if provided', function () {
serializer = sinon.stub();
params = {foo: 'bar'};
serializer.returns('foo=bar');
expect(buildURL('/foo', params, serializer)).toEqual('/foo?foo=bar');
expect(serializer.calledOnce).toBe(true);
expect(serializer.calledWith(params)).toBe(true);
});
it('should support URLSearchParams', function () {
expect(buildURL('/foo', new URLSearchParams('bar=baz'))).toEqual('/foo?bar=baz');
});
+4 -1
View File
@@ -20,7 +20,10 @@ const config: AxiosRequestConfig = {
],
headers: { 'X-FOO': 'bar' },
params: { id: 12345 },
paramsSerializer: (params: any) => 'id=12345',
paramsSerializer: {
indexes: true,
encode: (value) => value
},
data: { foo: 'bar' },
timeout: 10000,
withCredentials: true,