diff --git a/README.md b/README.md index d3dde6ec23..2badb8525a 100755 --- a/README.md +++ b/README.md @@ -332,7 +332,7 @@ These are the available config options for making requests. Only the `url` is re headers: {'X-Requested-With': 'XMLHttpRequest'}, // `params` are the URL parameters to be sent with the request - // Must be a plain object or a AxiosURLSearchParams object + // Must be a plain object or a URLSearchParams object params: { ID: 12345 }, @@ -346,7 +346,7 @@ These are the available config options for making requests. Only the `url` is re // `data` is the data to be sent as the request body // Only applicable for request methods 'PUT', 'POST', 'DELETE , and 'PATCH' // When no `transformRequest` is set, must be of one of the following types: - // - string, plain object, ArrayBuffer, ArrayBufferView, AxiosURLSearchParams + // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams // - Browser only: FormData, File, Blob // - Node only: Stream, Buffer data: { diff --git a/index.d.ts b/index.d.ts index 1f82f5080d..b98a5c617a 100644 --- a/index.d.ts +++ b/index.d.ts @@ -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, 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 { url?: string; method?: Method | string; @@ -114,7 +126,7 @@ export interface AxiosRequestConfig { transformResponse?: AxiosResponseTransformer | AxiosResponseTransformer[]; headers?: AxiosRequestHeaders; params?: any; - paramsSerializer?: (params: any) => string; + paramsSerializer?: ParamsSerializerOptions; data?: D; timeout?: number; timeoutErrorMessage?: string; diff --git a/lib/helpers/AxiosURLSearchParams.js b/lib/helpers/AxiosURLSearchParams.js index f46e8ce6e5..7c49f185f7 100644 --- a/lib/helpers/AxiosURLSearchParams.js +++ b/lib/helpers/AxiosURLSearchParams.js @@ -18,7 +18,7 @@ function encode(str) { } function AxiosURLSearchParams(params, options) { - this.pairs = []; + this._pairs = []; params && toFormData(params, this, options); } @@ -26,7 +26,7 @@ function AxiosURLSearchParams(params, options) { var prototype = AxiosURLSearchParams.prototype; prototype.append = function append(name, value) { - this.pairs.push([name, value]); + this._pairs.push([name, value]); }; prototype.toString = function toString(encoder) { @@ -34,7 +34,7 @@ prototype.toString = function toString(encoder) { return encoder.call(this, value, encode); } : encode; - return this.pairs.map(function each(pair) { + return this._pairs.map(function each(pair) { return _encode(pair[0]) + '=' + _encode(pair[1]); }, '').join('&'); }; diff --git a/lib/helpers/buildURL.js b/lib/helpers/buildURL.js index 2e498f76f0..bebacb3aee 100644 --- a/lib/helpers/buildURL.js +++ b/lib/helpers/buildURL.js @@ -1,5 +1,6 @@ 'use strict'; +var utils = require('../utils'); var AxiosURLSearchParams = require('../helpers/AxiosURLSearchParams'); function encode(val) { @@ -27,11 +28,20 @@ module.exports = function buildURL(url, params, options) { } var hashmarkIndex = url.indexOf('#'); + if (hashmarkIndex !== -1) { url = url.slice(0, hashmarkIndex); } - url += (url.indexOf('?') === -1 ? '?' : '&') + new AxiosURLSearchParams(params, options).toString(encode); + var _encode = options && options.encode || encode; + + var serializerParams = utils.isURLSearchParams(params) ? + params.toString() : + new AxiosURLSearchParams(params, options).toString(_encode); + + if (serializerParams) { + url += (url.indexOf('?') === -1 ? '?' : '&') + serializerParams; + } return url; }; diff --git a/test/specs/helpers/buildURL.spec.js b/test/specs/helpers/buildURL.spec.js index 7adf57449e..0bee3e9a05 100644 --- a/test/specs/helpers/buildURL.spec.js +++ b/test/specs/helpers/buildURL.spec.js @@ -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'); }); diff --git a/test/typescript/axios.ts b/test/typescript/axios.ts index 94d41602c1..c0c61599e1 100644 --- a/test/typescript/axios.ts +++ b/test/typescript/axios.ts @@ -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,