Skip to content

Commit

Permalink
Fixed merge conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonsaayman committed Apr 1, 2022
2 parents c855c9d + 6b9b05b commit 8699891
Show file tree
Hide file tree
Showing 22 changed files with 643 additions and 160 deletions.
129 changes: 100 additions & 29 deletions README.md
Expand Up @@ -23,7 +23,7 @@ Promise based HTTP client for the browser and node.js
- [Example](#example)
- [Axios API](#axios-api)
- [Request method aliases](#request-method-aliases)
- [Concurrency (Deprecated)](#concurrency-deprecated)
- [Concurrency 👎](#concurrency-deprecated)
- [Creating an instance](#creating-an-instance)
- [Instance methods](#instance-methods)
- [Request Config](#request-config)
Expand All @@ -36,11 +36,15 @@ Promise based HTTP client for the browser and node.js
- [Multiple Interceptors](#multiple-interceptors)
- [Handling Errors](#handling-errors)
- [Cancellation](#cancellation)
- [AbortController](#abortcontroller)
- [CancelToken 👎](#canceltoken-deprecated)
- [Using application/x-www-form-urlencoded format](#using-applicationx-www-form-urlencoded-format)
- [Browser](#browser)
- [Node.js](#nodejs)
- [Query string](#query-string)
- [Form data](#form-data)
- [Automatic serialization](#-automatic-serialization)
- [Manual FormData passing](#manual-formdata-passing)
- [Semver](#semver)
- [Promises](#promises)
- [TypeScript](#typescript)
Expand Down Expand Up @@ -494,6 +498,11 @@ These are the available config options for making requests. Only the `url` is re

// throw ETIMEDOUT error instead of generic ECONNABORTED on request timeouts
clarifyTimeoutError: false,
},

env: {
// The FormData class to be used to automatically serialize the payload into a FormData object
FormData: window?.FormData || global?.FormData
}
}
```
Expand Down Expand Up @@ -718,10 +727,30 @@ axios.get('/user/12345')
## Cancellation
You can cancel a request using a *cancel token*.
### AbortController
Starting from `v0.22.0` Axios supports AbortController to cancel requests in fetch API way:
```js
const controller = new AbortController();

axios.get('/foo/bar', {
signal: controller.signal
}).then(function(response) {
//...
});
// cancel the request
controller.abort()
```
### CancelToken `👎deprecated`
You can also cancel a request using a *CancelToken*.
> The axios cancel token API is based on the withdrawn [cancelable promises proposal](https://github.com/tc39/proposal-cancelable-promises).
> This API is deprecated since v0.22.0 and shouldn't be used in new projects
You can create a cancel token using the `CancelToken.source` factory as shown below:
```js
Expand Down Expand Up @@ -765,22 +794,11 @@ axios.get('/user/12345', {
cancel();
```
Axios supports AbortController to abort requests in [`fetch API`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API#aborting_a_fetch) way:
```js
const controller = new AbortController();

axios.get('/foo/bar', {
signal: controller.signal
}).then(function(response) {
//...
});
// cancel the request
controller.abort()
```

> Note: you can cancel several requests with the same cancel token/abort controller.
> If a cancellation token is already cancelled at the moment of starting an Axios request, then the request is cancelled immediately, without any attempts to make real request.
> During the transition period, you can use both cancellation APIs, even for the same request:
## Using application/x-www-form-urlencoded format
By default, axios serializes JavaScript objects to `JSON`. To send data in the `application/x-www-form-urlencoded` format instead, you can use one of the following options.
Expand Down Expand Up @@ -840,11 +858,75 @@ axios.post('http://something.com/', params.toString());
You can also use the [`qs`](https://github.com/ljharb/qs) library.
###### NOTE
The `qs` library is preferable if you need to stringify nested objects, as the `querystring` method has known issues with that use case (https://github.com/nodejs/node-v0.x-archive/issues/1665).
> NOTE:
> The `qs` library is preferable if you need to stringify nested objects, as the `querystring` method has [known issues](https://github.com/nodejs/node-v0.x-archive/issues/1665) with that use case.
#### Form data
##### 🆕 Automatic serialization
Starting from `v0.27.0`, Axios supports automatic object serialization to a FormData object if the request `Content-Type`
header is set to `multipart/form-data`.
The following request will submit the data in a FormData format (Browser & Node.js):
```js
import axios from 'axios';

axios.post('https://httpbin.org/post', {x: 1}, {
headers: {
'Content-Type': 'multipart/form-data'
}
}).then(({data})=> console.log(data));
```
In the `node.js` build, the ([`form-data`](https://github.com/form-data/form-data)) polyfill is used by default.
You can overload the FormData class by setting the `env.FormData` config variable,
but you probably won't need it in most cases:
```js
const axios= require('axios');
var FormData = require('form-data');

axios.post('https://httpbin.org/post', {x: 1, buf: new Buffer(10)}, {
headers: {
'Content-Type': 'multipart/form-data'
}
}).then(({data})=> console.log(data));
```
Axios FormData serializer supports some special endings to perform the following operations:
- `{}` - serialize the value with JSON.stringify
- `[]` - unwrap the array like object as separate fields with the same key
```js
const axios= require('axios');

axios.post('https://httpbin.org/post', {
'myObj{}': {x: 1, s: "foo"},
'files[]': document.querySelector('#fileInput').files
}, {
headers: {
'Content-Type': 'multipart/form-data'
}
}).then(({data})=> console.log(data));
```
Axios supports the following shortcut methods: `postForm`, `putForm`, `patchForm`
which are just the corresponding http methods with a header preset: `Content-Type`: `multipart/form-data`.
FileList object can be passed directly:
```js
await axios.postForm('https://httpbin.org/post', document.querySelector('#fileInput').files)
```
All files will be sent with the same field names: `files[]`;
##### Manual FormData passing
In node.js, you can use the [`form-data`](https://github.com/form-data/form-data) library as follows:
```js
Expand All @@ -855,18 +937,7 @@ form.append('my_field', 'my value');
form.append('my_buffer', new Buffer(10));
form.append('my_file', fs.createReadStream('/foo/bar.jpg'));

axios.post('https://example.com', form.getBuffer(), { headers: form.getHeaders() })
```

Alternatively, use an interceptor:

```js
axios.interceptors.request.use(config => {
if (config.data instanceof FormData) {
Object.assign(config.headers, config.data.getHeaders());
}
return config;
});
axios.post('https://example.com', form)
```
## Semver
Expand Down
6 changes: 6 additions & 0 deletions index.d.ts
Expand Up @@ -107,6 +107,9 @@ export interface AxiosRequestConfig<D = any> {
transitional?: TransitionalOptions;
signal?: AbortSignal;
insecureHTTPParser?: boolean;
env?: {
FormData?: new (...args: any[]) => object;
};
}

export interface HeadersDefaults {
Expand Down Expand Up @@ -224,6 +227,9 @@ export class Axios {
post<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
put<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
patch<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
postForm<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
putForm<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
patchForm<T = any, R = AxiosResponse<T>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>;
}

export interface AxiosInstance extends Axios {
Expand Down
5 changes: 4 additions & 1 deletion lib/adapters/http.js
Expand Up @@ -86,7 +86,10 @@ module.exports = function httpAdapter(config) {
headers['User-Agent'] = 'axios/' + VERSION;
}

if (data && !utils.isStream(data)) {
// support for https://www.npmjs.com/package/form-data api
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)) {
Expand Down
1 change: 1 addition & 0 deletions lib/axios.js
Expand Up @@ -41,6 +41,7 @@ axios.CanceledError = require('./cancel/CanceledError');
axios.CancelToken = require('./cancel/CancelToken');
axios.isCancel = require('./cancel/isCancel');
axios.VERSION = require('./env/data').version;
axios.toFormData = require('./helpers/toFormData');

// Expose AxiosError class
axios.AxiosError = require('../lib/core/AxiosError');
Expand Down
24 changes: 17 additions & 7 deletions lib/core/Axios.js
Expand Up @@ -138,13 +138,23 @@ utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData

utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
/*eslint func-names:0*/
Axios.prototype[method] = function(url, data, config) {
return this.request(mergeConfig(config || {}, {
method: method,
url: url,
data: data
}));
};

function generateHTTPMethod(isForm) {
return function httpMethod(url, data, config) {
return this.request(mergeConfig(config || {}, {
method: method,
headers: isForm ? {
'Content-Type': 'multipart/form-data'
} : {},
url: url,
data: data
}));
};
}

Axios.prototype[method] = generateHTTPMethod();

Axios.prototype[method + 'Form'] = generateHTTPMethod(true);
});

module.exports = Axios;
2 changes: 2 additions & 0 deletions lib/defaults/env/FormData.js
@@ -0,0 +1,2 @@
// eslint-disable-next-line strict
module.exports = require('form-data');
17 changes: 16 additions & 1 deletion lib/defaults/index.js
Expand Up @@ -4,6 +4,7 @@ var utils = require('../utils');
var normalizeHeaderName = require('../helpers/normalizeHeaderName');
var AxiosError = require('../core/AxiosError');
var transitionalDefaults = require('./transitional');
var toFormData = require('./helpers/toFormData');

var DEFAULT_CONTENT_TYPE = {
'Content-Type': 'application/x-www-form-urlencoded'
Expand Down Expand Up @@ -68,10 +69,20 @@ 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'];

var isFileList;

if ((isFileList = utils.isFileList(data)) || (isObjectPayload && contentType === 'multipart/form-data')) {
var _FormData = this.env && this.env.FormData;
return toFormData(isFileList ? {'files[]': data} : data, _FormData && new _FormData());
} else if (isObjectPayload || contentType === 'application/json') {
setContentTypeIfUnset(headers, 'application/json');
return stringifySafely(data);
}

return data;
}],

Expand Down Expand Up @@ -109,6 +120,10 @@ var defaults = {
maxContentLength: -1,
maxBodyLength: -1,

env: {
FormData: require('./defaults/env/FormData')
},

validateStatus: function validateStatus(status) {
return status >= 200 && status < 300;
},
Expand Down
2 changes: 2 additions & 0 deletions lib/helpers/null.js
@@ -0,0 +1,2 @@
// eslint-disable-next-line strict
module.exports = null;

0 comments on commit 8699891

Please sign in to comment.