2
0
mirror of https://github.com/tenrok/axios.git synced 2026-06-17 19:21:29 +03:00

Fix: Don't add null values to query string. (#5108)

* feat: add  boolean flag to mimic pre 1.x behavior for paramsSerializer custom function

* chore: update ParamsSerializer Readme

* fix: dont slice hash off URL if not appending params

* Omit nulls from formData serialization

* fix: dont add nulls or undefined values to arrays either

* readme update

* fix test

* chore: documentation

* chore: do TS properly

Co-authored-by: Jay <jasonsaayman@gmail.com>
This commit is contained in:
ChronosMasterOfAllTime
2022-10-15 08:01:59 -05:00
committed by GitHub
parent ef1c48a476
commit b0ebf9fcac
6 changed files with 37 additions and 15 deletions
Executable → Regular
+2
View File
@@ -358,6 +358,8 @@ These are the available config options for making requests. Only the `url` is re
// `paramsSerializer` is an optional config in charge of serializing `params` // `paramsSerializer` is an optional config in charge of serializing `params`
paramsSerializer: { paramsSerializer: {
encode?: (param: string): string => { /* Do custom ops here and return transformed string */ }, // custom encoder function; sends Key/Values in an iterative fashion
serialize?: (params: Record<string, any>, options?: ParamsSerializerOptions ), // mimic pre 1.x behavior and send entire params object to a custom serializer func. Allows consumer to control how params are serialized.
indexes: false // array indexes format (null - no brackets, false (default) - empty brackets, true - brackets with indexes) indexes: false // array indexes format (null - no brackets, false (default) - empty brackets, true - brackets with indexes)
}, },
Vendored
+1 -1
View File
@@ -248,7 +248,7 @@ export interface ParamEncoder {
} }
export interface CustomParamsSerializer { export interface CustomParamsSerializer {
(params: object, options?: ParamsSerializerOptions): string; (params: Record<string, any>, options?: ParamsSerializerOptions): string;
} }
export interface ParamsSerializerOptions extends SerializerOptions { export interface ParamsSerializerOptions extends SerializerOptions {
+5 -6
View File
@@ -36,12 +36,6 @@ export default function buildURL(url, params, options) {
return url; return url;
} }
const hashmarkIndex = url.indexOf('#');
if (hashmarkIndex !== -1) {
url = url.slice(0, hashmarkIndex);
}
const _encode = options && options.encode || encode; const _encode = options && options.encode || encode;
const serializeFn = options && options.serialize; const serializeFn = options && options.serialize;
@@ -57,6 +51,11 @@ export default function buildURL(url, params, options) {
} }
if (serializedParams) { if (serializedParams) {
const hashmarkIndex = url.indexOf("#");
if (hashmarkIndex !== -1) {
url = url.slice(0, hashmarkIndex);
}
url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams; url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams;
} }
+2 -2
View File
@@ -168,7 +168,7 @@ function toFormData(obj, formData, options) {
key = removeBrackets(key); key = removeBrackets(key);
arr.forEach(function each(el, index) { arr.forEach(function each(el, index) {
!utils.isUndefined(el) && formData.append( !(utils.isUndefined(el) || el === null) && formData.append(
// eslint-disable-next-line no-nested-ternary // eslint-disable-next-line no-nested-ternary
indexes === true ? renderKey([key], index, dots) : (indexes === null ? key : key + '[]'), indexes === true ? renderKey([key], index, dots) : (indexes === null ? key : key + '[]'),
convertValue(el) convertValue(el)
@@ -205,7 +205,7 @@ function toFormData(obj, formData, options) {
stack.push(value); stack.push(value);
utils.forEach(value, function each(el, key) { utils.forEach(value, function each(el, key) {
const result = !utils.isUndefined(el) && visitor.call( const result = !(utils.isUndefined(el) || el === null) && visitor.call(
formData, el, utils.isString(key) ? key.trim() : key, path, exposedHelpers formData, el, utils.isString(key) ? key.trim() : key, path, exposedHelpers
); );
+23 -2
View File
@@ -8,10 +8,31 @@ describe('helpers::buildURL', function () {
it('should support params', function () { it('should support params', function () {
expect(buildURL('/foo', { expect(buildURL('/foo', {
foo: 'bar' foo: 'bar',
isUndefined: undefined,
isNull: null
})).toEqual('/foo?foo=bar'); })).toEqual('/foo?foo=bar');
}); });
it('should support sending raw params to custom serializer func', function () {
const serializer = sinon.stub();
const params = { foo: "bar" };
serializer.returns("foo=bar");
expect(
buildURL(
"/foo",
{
foo: "bar",
},
{
serialize: serializer,
}
)
).toEqual("/foo?foo=bar");
expect(serializer.calledOnce).toBe(true);
expect(serializer.calledWith(params)).toBe(true);
});
it('should support object params', function () { it('should support object params', function () {
expect(buildURL('/foo', { expect(buildURL('/foo', {
foo: { foo: {
@@ -30,7 +51,7 @@ describe('helpers::buildURL', function () {
it('should support array params', function () { it('should support array params', function () {
expect(buildURL('/foo', { expect(buildURL('/foo', {
foo: ['bar', 'baz'] foo: ['bar', 'baz', null, undefined]
})).toEqual('/foo?foo[]=bar&foo[]=baz'); })).toEqual('/foo?foo[]=bar&foo[]=baz');
}); });
+3 -3
View File
@@ -6,7 +6,7 @@ import axios, {
AxiosAdapter, AxiosAdapter,
Cancel, Cancel,
CancelTokenSource, CancelTokenSource,
Canceler, AxiosProgressEvent Canceler, AxiosProgressEvent, ParamsSerializerOptions
} from 'axios'; } from 'axios';
const config: AxiosRequestConfig = { const config: AxiosRequestConfig = {
@@ -21,8 +21,8 @@ const config: AxiosRequestConfig = {
params: { id: 12345 }, params: { id: 12345 },
paramsSerializer: { paramsSerializer: {
indexes: true, indexes: true,
encode: (value) => value, encode: (value: any) => value,
serialize: (value, options) => String(value) serialize: (value: Record<string, any>, options?: ParamsSerializerOptions) => String(value)
}, },
data: { foo: 'bar' }, data: { foo: 'bar' },
timeout: 10000, timeout: 10000,