axios 1.2.6 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of axios might be problematic. Click here for more details.
- package/CHANGELOG.md +18 -0
- package/dist/axios.js +50 -24
- package/dist/axios.js.map +1 -1
- package/dist/axios.min.js +1 -1
- package/dist/axios.min.js.map +1 -1
- package/dist/browser/axios.cjs +55 -25
- package/dist/browser/axios.cjs.map +1 -1
- package/dist/esm/axios.js +55 -25
- package/dist/esm/axios.js.map +1 -1
- package/dist/esm/axios.min.js +1 -1
- package/dist/esm/axios.min.js.map +1 -1
- package/dist/node/axios.cjs +229 -20
- package/dist/node/axios.cjs.map +1 -1
- package/index.d.cts +1 -1
- package/index.d.ts +1 -1
- package/lib/adapters/http.js +32 -3
- package/lib/core/AxiosHeaders.js +14 -2
- package/lib/env/classes/FormData.js +2 -2
- package/lib/env/data.js +1 -1
- package/lib/helpers/ZlibHeaderTransformStream.js +28 -0
- package/lib/helpers/formDataToStream.js +110 -0
- package/lib/helpers/readBlob.js +15 -0
- package/lib/helpers/toFormData.js +4 -14
- package/lib/utils.js +35 -1
- package/package.json +7 -4
package/index.d.cts
CHANGED
package/index.d.ts
CHANGED
package/lib/adapters/http.js
CHANGED
@@ -19,6 +19,9 @@ import stream from 'stream';
|
|
19
19
|
import AxiosHeaders from '../core/AxiosHeaders.js';
|
20
20
|
import AxiosTransformStream from '../helpers/AxiosTransformStream.js';
|
21
21
|
import EventEmitter from 'events';
|
22
|
+
import formDataToStream from "../helpers/formDataToStream.js";
|
23
|
+
import readBlob from "../helpers/readBlob.js";
|
24
|
+
import ZlibHeaderTransformStream from '../helpers/ZlibHeaderTransformStream.js';
|
22
25
|
|
23
26
|
const zlibOptions = {
|
24
27
|
flush: zlib.constants.Z_SYNC_FLUSH,
|
@@ -242,9 +245,27 @@ export default isHttpAdapterSupported && function httpAdapter(config) {
|
|
242
245
|
let maxUploadRate = undefined;
|
243
246
|
let maxDownloadRate = undefined;
|
244
247
|
|
245
|
-
// support for
|
246
|
-
if (utils.
|
248
|
+
// support for spec compliant FormData objects
|
249
|
+
if (utils.isSpecCompliantForm(data)) {
|
250
|
+
const userBoundary = headers.getContentType(/boundary=([-_\w\d]{10,70})/i);
|
251
|
+
|
252
|
+
data = formDataToStream(data, (formHeaders) => {
|
253
|
+
headers.set(formHeaders);
|
254
|
+
}, {
|
255
|
+
tag: `axios-${VERSION}-boundary`,
|
256
|
+
boundary: userBoundary && userBoundary[1] || undefined
|
257
|
+
});
|
258
|
+
// support for https://www.npmjs.com/package/form-data api
|
259
|
+
} else if (utils.isFormData(data) && utils.isFunction(data.getHeaders)) {
|
247
260
|
headers.set(data.getHeaders());
|
261
|
+
if (utils.isFunction(data.getLengthSync)) { // check if the undocumented API exists
|
262
|
+
const knownLength = data.getLengthSync();
|
263
|
+
!utils.isUndefined(knownLength) && headers.setContentLength(knownLength, false);
|
264
|
+
}
|
265
|
+
} else if (utils.isBlob(data)) {
|
266
|
+
data.size && headers.setContentType(data.type || 'application/octet-stream');
|
267
|
+
headers.setContentLength(data.size || 0);
|
268
|
+
data = stream.Readable.from(readBlob(data));
|
248
269
|
} else if (data && !utils.isStream(data)) {
|
249
270
|
if (Buffer.isBuffer(data)) {
|
250
271
|
// Nothing to do...
|
@@ -261,7 +282,7 @@ export default isHttpAdapterSupported && function httpAdapter(config) {
|
|
261
282
|
}
|
262
283
|
|
263
284
|
// Add Content-Length header if data exists
|
264
|
-
headers.
|
285
|
+
headers.setContentLength(data.length, false);
|
265
286
|
|
266
287
|
if (config.maxBodyLength > -1 && data.length > config.maxBodyLength) {
|
267
288
|
return reject(new AxiosError(
|
@@ -425,7 +446,15 @@ export default isHttpAdapterSupported && function httpAdapter(config) {
|
|
425
446
|
case 'x-gzip':
|
426
447
|
case 'compress':
|
427
448
|
case 'x-compress':
|
449
|
+
// add the unzipper to the body stream processing pipeline
|
450
|
+
streams.push(zlib.createUnzip(zlibOptions));
|
451
|
+
|
452
|
+
// remove the content-encoding in order to not confuse downstream operations
|
453
|
+
delete res.headers['content-encoding'];
|
454
|
+
break;
|
428
455
|
case 'deflate':
|
456
|
+
streams.push(new ZlibHeaderTransformStream());
|
457
|
+
|
429
458
|
// add the unzipper to the body stream processing pipeline
|
430
459
|
streams.push(zlib.createUnzip(zlibOptions));
|
431
460
|
|
package/lib/core/AxiosHeaders.js
CHANGED
@@ -174,8 +174,20 @@ class AxiosHeaders {
|
|
174
174
|
return deleted;
|
175
175
|
}
|
176
176
|
|
177
|
-
clear() {
|
178
|
-
|
177
|
+
clear(matcher) {
|
178
|
+
const keys = Object.keys(this);
|
179
|
+
let i = keys.length;
|
180
|
+
let deleted = false;
|
181
|
+
|
182
|
+
while (i--) {
|
183
|
+
const key = keys[i];
|
184
|
+
if(!matcher || matchHeaderValue(this, this[key], key, matcher)) {
|
185
|
+
delete this[key];
|
186
|
+
deleted = true;
|
187
|
+
}
|
188
|
+
}
|
189
|
+
|
190
|
+
return deleted;
|
179
191
|
}
|
180
192
|
|
181
193
|
normalize(format) {
|
@@ -1,2 +1,2 @@
|
|
1
|
-
import
|
2
|
-
export default FormData;
|
1
|
+
import _FormData from 'form-data';
|
2
|
+
export default typeof FormData !== 'undefined' ? FormData : _FormData;
|
package/lib/env/data.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
export const VERSION = "1.
|
1
|
+
export const VERSION = "1.3.0";
|
@@ -0,0 +1,28 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
import stream from "stream";
|
4
|
+
|
5
|
+
class ZlibHeaderTransformStream extends stream.Transform {
|
6
|
+
__transform(chunk, encoding, callback) {
|
7
|
+
this.push(chunk);
|
8
|
+
callback();
|
9
|
+
}
|
10
|
+
|
11
|
+
_transform(chunk, encoding, callback) {
|
12
|
+
if (chunk.length !== 0) {
|
13
|
+
this._transform = this.__transform;
|
14
|
+
|
15
|
+
// Add Default Compression headers if no zlib headers are present
|
16
|
+
if (chunk[0] !== 120) { // Hex: 78
|
17
|
+
const header = Buffer.alloc(2);
|
18
|
+
header[0] = 120; // Hex: 78
|
19
|
+
header[1] = 156; // Hex: 9C
|
20
|
+
this.push(header, encoding);
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
24
|
+
this.__transform(chunk, encoding, callback);
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
export default ZlibHeaderTransformStream;
|
@@ -0,0 +1,110 @@
|
|
1
|
+
import {Readable} from 'stream';
|
2
|
+
import utils from "../utils.js";
|
3
|
+
import readBlob from "./readBlob.js";
|
4
|
+
|
5
|
+
const BOUNDARY_ALPHABET = utils.ALPHABET.ALPHA_DIGIT + '-_';
|
6
|
+
|
7
|
+
const textEncoder = new TextEncoder();
|
8
|
+
|
9
|
+
const CRLF = '\r\n';
|
10
|
+
const CRLF_BYTES = textEncoder.encode(CRLF);
|
11
|
+
const CRLF_BYTES_COUNT = 2;
|
12
|
+
|
13
|
+
class FormDataPart {
|
14
|
+
constructor(name, value) {
|
15
|
+
const {escapeName} = this.constructor;
|
16
|
+
const isStringValue = utils.isString(value);
|
17
|
+
|
18
|
+
let headers = `Content-Disposition: form-data; name="${escapeName(name)}"${
|
19
|
+
!isStringValue && value.name ? `; filename="${escapeName(value.name)}"` : ''
|
20
|
+
}${CRLF}`;
|
21
|
+
|
22
|
+
if (isStringValue) {
|
23
|
+
value = textEncoder.encode(String(value).replace(/\r?\n|\r\n?/g, CRLF));
|
24
|
+
} else {
|
25
|
+
headers += `Content-Type: ${value.type || "application/octet-stream"}${CRLF}`
|
26
|
+
}
|
27
|
+
|
28
|
+
this.headers = textEncoder.encode(headers + CRLF);
|
29
|
+
|
30
|
+
this.contentLength = isStringValue ? value.byteLength : value.size;
|
31
|
+
|
32
|
+
this.size = this.headers.byteLength + this.contentLength + CRLF_BYTES_COUNT;
|
33
|
+
|
34
|
+
this.name = name;
|
35
|
+
this.value = value;
|
36
|
+
}
|
37
|
+
|
38
|
+
async *encode(){
|
39
|
+
yield this.headers;
|
40
|
+
|
41
|
+
const {value} = this;
|
42
|
+
|
43
|
+
if(utils.isTypedArray(value)) {
|
44
|
+
yield value;
|
45
|
+
} else {
|
46
|
+
yield* readBlob(value);
|
47
|
+
}
|
48
|
+
|
49
|
+
yield CRLF_BYTES;
|
50
|
+
}
|
51
|
+
|
52
|
+
static escapeName(name) {
|
53
|
+
return String(name).replace(/[\r\n"]/g, (match) => ({
|
54
|
+
'\r' : '%0D',
|
55
|
+
'\n' : '%0A',
|
56
|
+
'"' : '%22',
|
57
|
+
}[match]));
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
const formDataToStream = (form, headersHandler, options) => {
|
62
|
+
const {
|
63
|
+
tag = 'form-data-boundary',
|
64
|
+
size = 25,
|
65
|
+
boundary = tag + '-' + utils.generateString(size, BOUNDARY_ALPHABET)
|
66
|
+
} = options || {};
|
67
|
+
|
68
|
+
if(!utils.isFormData(form)) {
|
69
|
+
throw TypeError('FormData instance required');
|
70
|
+
}
|
71
|
+
|
72
|
+
if (boundary.length < 1 || boundary.length > 70) {
|
73
|
+
throw Error('boundary must be 10-70 characters long')
|
74
|
+
}
|
75
|
+
|
76
|
+
const boundaryBytes = textEncoder.encode('--' + boundary + CRLF);
|
77
|
+
const footerBytes = textEncoder.encode('--' + boundary + '--' + CRLF + CRLF);
|
78
|
+
let contentLength = footerBytes.byteLength;
|
79
|
+
|
80
|
+
const parts = Array.from(form.entries()).map(([name, value]) => {
|
81
|
+
const part = new FormDataPart(name, value);
|
82
|
+
contentLength += part.size;
|
83
|
+
return part;
|
84
|
+
});
|
85
|
+
|
86
|
+
contentLength += boundaryBytes.byteLength * parts.length;
|
87
|
+
|
88
|
+
contentLength = utils.toFiniteNumber(contentLength);
|
89
|
+
|
90
|
+
const computedHeaders = {
|
91
|
+
'Content-Type': `multipart/form-data; boundary=${boundary}`
|
92
|
+
}
|
93
|
+
|
94
|
+
if (Number.isFinite(contentLength)) {
|
95
|
+
computedHeaders['Content-Length'] = contentLength;
|
96
|
+
}
|
97
|
+
|
98
|
+
headersHandler && headersHandler(computedHeaders);
|
99
|
+
|
100
|
+
return Readable.from((async function *() {
|
101
|
+
for(const part of parts) {
|
102
|
+
yield boundaryBytes;
|
103
|
+
yield* part.encode();
|
104
|
+
}
|
105
|
+
|
106
|
+
yield footerBytes;
|
107
|
+
})());
|
108
|
+
};
|
109
|
+
|
110
|
+
export default formDataToStream;
|
@@ -0,0 +1,15 @@
|
|
1
|
+
const {asyncIterator} = Symbol;
|
2
|
+
|
3
|
+
const readBlob = async function* (blob) {
|
4
|
+
if (blob.stream) {
|
5
|
+
yield* blob.stream()
|
6
|
+
} else if (blob.arrayBuffer) {
|
7
|
+
yield await blob.arrayBuffer()
|
8
|
+
} else if (blob[asyncIterator]) {
|
9
|
+
yield* blob[asyncIterator]();
|
10
|
+
} else {
|
11
|
+
yield blob;
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
export default readBlob;
|
@@ -2,7 +2,8 @@
|
|
2
2
|
|
3
3
|
import utils from '../utils.js';
|
4
4
|
import AxiosError from '../core/AxiosError.js';
|
5
|
-
|
5
|
+
// temporary hotfix to avoid circular references until AxiosURLSearchParams is refactored
|
6
|
+
import PlatformFormData from '../platform/node/classes/FormData.js';
|
6
7
|
|
7
8
|
/**
|
8
9
|
* Determines if the given thing is a array or js object.
|
@@ -59,17 +60,6 @@ const predicates = utils.toFlatObject(utils, {}, null, function filter(prop) {
|
|
59
60
|
return /^is[A-Z]/.test(prop);
|
60
61
|
});
|
61
62
|
|
62
|
-
/**
|
63
|
-
* If the thing is a FormData object, return true, otherwise return false.
|
64
|
-
*
|
65
|
-
* @param {unknown} thing - The thing to check.
|
66
|
-
*
|
67
|
-
* @returns {boolean}
|
68
|
-
*/
|
69
|
-
function isSpecCompliant(thing) {
|
70
|
-
return thing && utils.isFunction(thing.append) && thing[Symbol.toStringTag] === 'FormData' && thing[Symbol.iterator];
|
71
|
-
}
|
72
|
-
|
73
63
|
/**
|
74
64
|
* Convert a data object to FormData
|
75
65
|
*
|
@@ -99,7 +89,7 @@ function toFormData(obj, formData, options) {
|
|
99
89
|
}
|
100
90
|
|
101
91
|
// eslint-disable-next-line no-param-reassign
|
102
|
-
formData = formData || new (
|
92
|
+
formData = formData || new (PlatformFormData || FormData)();
|
103
93
|
|
104
94
|
// eslint-disable-next-line no-param-reassign
|
105
95
|
options = utils.toFlatObject(options, {
|
@@ -117,7 +107,7 @@ function toFormData(obj, formData, options) {
|
|
117
107
|
const dots = options.dots;
|
118
108
|
const indexes = options.indexes;
|
119
109
|
const _Blob = options.Blob || typeof Blob !== 'undefined' && Blob;
|
120
|
-
const useBlob = _Blob &&
|
110
|
+
const useBlob = _Blob && utils.isSpecCompliantForm(formData);
|
121
111
|
|
122
112
|
if (!utils.isFunction(visitor)) {
|
123
113
|
throw new TypeError('visitor must be a function');
|
package/lib/utils.js
CHANGED
@@ -512,7 +512,7 @@ const matchAll = (regExp, str) => {
|
|
512
512
|
const isHTMLForm = kindOfTest('HTMLFormElement');
|
513
513
|
|
514
514
|
const toCamelCase = str => {
|
515
|
-
return str.toLowerCase().replace(/[_
|
515
|
+
return str.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,
|
516
516
|
function replacer(m, p1, p2) {
|
517
517
|
return p1.toUpperCase() + p2;
|
518
518
|
}
|
@@ -596,6 +596,37 @@ const toFiniteNumber = (value, defaultValue) => {
|
|
596
596
|
return Number.isFinite(value) ? value : defaultValue;
|
597
597
|
}
|
598
598
|
|
599
|
+
const ALPHA = 'abcdefghijklmnopqrstuvwxyz'
|
600
|
+
|
601
|
+
const DIGIT = '0123456789';
|
602
|
+
|
603
|
+
const ALPHABET = {
|
604
|
+
DIGIT,
|
605
|
+
ALPHA,
|
606
|
+
ALPHA_DIGIT: ALPHA + ALPHA.toUpperCase() + DIGIT
|
607
|
+
}
|
608
|
+
|
609
|
+
const generateString = (size = 16, alphabet = ALPHABET.ALPHA_DIGIT) => {
|
610
|
+
let str = '';
|
611
|
+
const {length} = alphabet;
|
612
|
+
while (size--) {
|
613
|
+
str += alphabet[Math.random() * length|0]
|
614
|
+
}
|
615
|
+
|
616
|
+
return str;
|
617
|
+
}
|
618
|
+
|
619
|
+
/**
|
620
|
+
* If the thing is a FormData object, return true, otherwise return false.
|
621
|
+
*
|
622
|
+
* @param {unknown} thing - The thing to check.
|
623
|
+
*
|
624
|
+
* @returns {boolean}
|
625
|
+
*/
|
626
|
+
function isSpecCompliantForm(thing) {
|
627
|
+
return !!(thing && isFunction(thing.append) && thing[Symbol.toStringTag] === 'FormData' && thing[Symbol.iterator]);
|
628
|
+
}
|
629
|
+
|
599
630
|
const toJSONObject = (obj) => {
|
600
631
|
const stack = new Array(10);
|
601
632
|
|
@@ -673,5 +704,8 @@ export default {
|
|
673
704
|
findKey,
|
674
705
|
global: _global,
|
675
706
|
isContextDefined,
|
707
|
+
ALPHABET,
|
708
|
+
generateString,
|
709
|
+
isSpecCompliantForm,
|
676
710
|
toJSONObject
|
677
711
|
};
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "axios",
|
3
|
-
"version": "1.
|
3
|
+
"version": "1.3.0",
|
4
4
|
"description": "Promise based HTTP client for the browser and node.js",
|
5
5
|
"main": "index.js",
|
6
6
|
"exports": {
|
@@ -89,6 +89,7 @@
|
|
89
89
|
"es6-promise": "^4.2.8",
|
90
90
|
"eslint": "^8.17.0",
|
91
91
|
"express": "^4.18.1",
|
92
|
+
"formdata-node": "^5.0.0",
|
92
93
|
"formidable": "^2.0.1",
|
93
94
|
"fs-extra": "^10.1.0",
|
94
95
|
"get-stream": "^3.0.0",
|
@@ -126,7 +127,8 @@
|
|
126
127
|
},
|
127
128
|
"browser": {
|
128
129
|
"./lib/adapters/http.js": "./lib/helpers/null.js",
|
129
|
-
"./lib/platform/node/index.js": "./lib/platform/browser/index.js"
|
130
|
+
"./lib/platform/node/index.js": "./lib/platform/browser/index.js",
|
131
|
+
"./lib/platform/node/classes/FormData.js": "./lib/helpers/null.js"
|
130
132
|
},
|
131
133
|
"jsdelivr": "dist/axios.min.js",
|
132
134
|
"unpkg": "dist/axios.min.js",
|
@@ -165,7 +167,8 @@
|
|
165
167
|
"push": true,
|
166
168
|
"commit": true,
|
167
169
|
"tag": true,
|
168
|
-
"requireCommits": false
|
170
|
+
"requireCommits": false,
|
171
|
+
"requireCleanWorkingDir": false
|
169
172
|
},
|
170
173
|
"github": {
|
171
174
|
"release": true,
|
@@ -184,7 +187,7 @@
|
|
184
187
|
},
|
185
188
|
"hooks": {
|
186
189
|
"before:init": "npm test",
|
187
|
-
"after:bump": "gulp version --bump ${version} && npm run build && npm run test:build:version && git add ./dist",
|
190
|
+
"after:bump": "gulp version --bump ${version} && npm run build && npm run test:build:version && git add ./dist && git add ./package-lock.json",
|
188
191
|
"before:release": "npm run release:changelog:fix",
|
189
192
|
"after:release": "echo Successfully released ${name} v${version} to ${repo.repository}."
|
190
193
|
}
|