From cc86c6c49fdbfd8e2517b191b8833d2f2816ff91 Mon Sep 17 00:00:00 2001 From: Jay Date: Thu, 27 Jan 2022 08:39:25 +0200 Subject: [PATCH 1/2] Fix/remove url required (#4426) * Removed error when url is null as this breaks current use cases for alot of projects * Removed associated tests that check for the for url to not be empty --- lib/core/Axios.js | 7 ------- test/specs/requests.spec.js | 18 ------------------ 2 files changed, 25 deletions(-) diff --git a/lib/core/Axios.js b/lib/core/Axios.js index d7ce7db..a1be08a 100644 --- a/lib/core/Axios.js +++ b/lib/core/Axios.js @@ -36,10 +36,6 @@ Axios.prototype.request = function request(configOrUrl, config) { config = configOrUrl || {}; } - if (!config.url) { - throw new Error('Provided config url is not valid'); - } - config = mergeConfig(this.defaults, config); // Set config.method @@ -122,9 +118,6 @@ Axios.prototype.request = function request(configOrUrl, config) { }; Axios.prototype.getUri = function getUri(config) { - if (!config.url) { - throw new Error('Provided config url is not valid'); - } config = mergeConfig(this.defaults, config); return buildURL(config.url, config.params, config.paramsSerializer).replace(/^\?/, ''); }; diff --git a/test/specs/requests.spec.js b/test/specs/requests.spec.js index e363fef..a5aa81a 100644 --- a/test/specs/requests.spec.js +++ b/test/specs/requests.spec.js @@ -7,24 +7,6 @@ describe('requests', function () { jasmine.Ajax.uninstall(); }); - it('should throw error when missing url', function (done) { - expect(() => axios()).toThrowError(/Provided config url is not valid/); - done(); - - expect(() => axios('')).toThrowError(/Provided config url is not valid/); - done(); - - expect(() => axios({ - url: undefined, - })).toThrowError(/Provided config url is not valid/); - done(); - - expect(() => axios({ - method: 'POST', - })).toThrowError(/Provided config url is not valid/); - done(); - }); - it('should treat single string arg as url', function (done) { axios('/foo'); From 73e3bdb8835ba942096b662e9441f1d85ce4d484 Mon Sep 17 00:00:00 2001 From: Dmitriy Mozgovoy Date: Wed, 2 Feb 2022 13:48:44 +0200 Subject: [PATCH 2/2] Fixed isFormData predicate; (#4413) Added support for automatic object serialization to FormData if `Content-Type` is `multipart/form-data`; Added support for FormData to be overloaded using `config.env.FormData` option; Added support for FormData in node.js environment through `form-data` package; --- index.d.ts | 3 +++ lib/adapters/http.js | 4 +++- lib/defaults.js | 12 +++++++++++- lib/helpers/toFormData.js | 10 +++++++--- lib/utils.js | 24 +++++++++++++++--------- test/specs/helpers/toFormData.spec.js | 2 +- 6 files changed, 40 insertions(+), 15 deletions(-) diff --git a/index.d.ts b/index.d.ts index b681915..5cb94c5 100644 --- a/index.d.ts +++ b/index.d.ts @@ -107,6 +107,9 @@ export interface AxiosRequestConfig { transitional?: TransitionalOptions; signal?: AbortSignal; insecureHTTPParser?: boolean; + env?: { + FormData?: new (...args: any[]) => object; + }; } export interface HeadersDefaults { diff --git a/lib/adapters/http.js b/lib/adapters/http.js index 951e400..5753fbd 100755 --- a/lib/adapters/http.js +++ b/lib/adapters/http.js @@ -87,7 +87,9 @@ module.exports = function httpAdapter(config) { headers['User-Agent'] = 'axios/' + VERSION; } - if (data && !utils.isStream(data)) { + if (utils.isFormData(data) && utils.isFunction(data.getHeaders)) { + Object.assign(headers, data.getHeaders()); + } else if (data && !utils.isStream(data)) { if (Buffer.isBuffer(data)) { // Nothing to do... } else if (utils.isArrayBuffer(data)) { diff --git a/lib/defaults.js b/lib/defaults.js index eaee189..cb061af 100644 --- a/lib/defaults.js +++ b/lib/defaults.js @@ -3,6 +3,7 @@ var utils = require('./utils'); var normalizeHeaderName = require('./helpers/normalizeHeaderName'); var enhanceError = require('./core/enhanceError'); +var toFormData = require('./helpers/toFormData'); var DEFAULT_CONTENT_TYPE = { 'Content-Type': 'application/x-www-form-urlencoded' @@ -71,10 +72,17 @@ var defaults = { setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8'); return data.toString(); } - if (utils.isObject(data) || (headers && headers['Content-Type'] === 'application/json')) { + + var isObjectPayload = utils.isObject(data); + var contentType = headers && headers['Content-Type']; + + if ( isObjectPayload && contentType === 'multipart/form-data' ) { + return toFormData(data, new (this.env && this.env.FormData || FormData)); + } else if ( isObjectPayload || contentType === 'application/json' ) { setContentTypeIfUnset(headers, 'application/json'); return stringifySafely(data); } + return data; }], @@ -112,6 +120,8 @@ var defaults = { maxContentLength: -1, maxBodyLength: -1, + env: {}, + validateStatus: function validateStatus(status) { return status >= 200 && status < 300; }, diff --git a/lib/helpers/toFormData.js b/lib/helpers/toFormData.js index e21d0a7..0f03b79 100644 --- a/lib/helpers/toFormData.js +++ b/lib/helpers/toFormData.js @@ -1,5 +1,7 @@ 'use strict'; +var utils = require('../utils'); + function combinedKey(parentKey, elKey) { return parentKey + '.' + elKey; } @@ -11,7 +13,7 @@ function buildFormData(formData, data, parentKey) { }); } else if ( typeof data === 'object' && - !(data instanceof File || data === null) + !(utils.isFile(data) || data === null) ) { Object.keys(data).forEach(function buildObject(key) { buildFormData( @@ -44,10 +46,12 @@ function buildFormData(formData, data, parentKey) { * type FormVal = FormDataNest | FormDataPrimitive * * @param {FormVal} data + * @param {?Object} formData */ -module.exports = function getFormData(data) { - var formData = new FormData(); +module.exports = function getFormData(data, formData) { + // eslint-disable-next-line no-param-reassign + formData = formData || new FormData(); buildFormData(formData, data); diff --git a/lib/utils.js b/lib/utils.js index f0f9043..536fbf9 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -47,15 +47,6 @@ function isArrayBuffer(val) { return toString.call(val) === '[object ArrayBuffer]'; } -/** - * Determine if a value is a FormData - * - * @param {Object} val The value to test - * @returns {boolean} True if value is an FormData, otherwise false - */ -function isFormData(val) { - return toString.call(val) === '[object FormData]'; -} /** * Determine if a value is a view on an ArrayBuffer @@ -168,6 +159,21 @@ function isStream(val) { return isObject(val) && isFunction(val.pipe); } +/** + * Determine if a value is a FormData + * + * @param {Object} thing The value to test + * @returns {boolean} True if value is an FormData, otherwise false + */ +function isFormData(thing) { + var pattern = '[object FormData]'; + return thing && ( + (typeof FormData === 'function' && thing instanceof FormData) || + toString.call(thing) === pattern || + (isFunction(thing.toString) && thing.toString() === pattern) + ); +} + /** * Determine if a value is a URLSearchParams object * diff --git a/test/specs/helpers/toFormData.spec.js b/test/specs/helpers/toFormData.spec.js index f28471e..ec16252 100644 --- a/test/specs/helpers/toFormData.spec.js +++ b/test/specs/helpers/toFormData.spec.js @@ -1,7 +1,7 @@ var toFormData = require("../../../lib/helpers/toFormData"); describe("toFormData", function () { - it("Convert nested data object to FormDAta", function () { + it("Convert nested data object to FormData", function () { var o = { val: 123, nested: {