axios 0.21.1 → 0.22.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.
- package/CHANGELOG.md +115 -8
- package/README.md +97 -5
- package/SECURITY.md +5 -0
- package/dist/axios.js +2102 -1583
- package/dist/axios.map +1 -1
- package/dist/axios.min.js +1 -2
- package/dist/axios.min.map +1 -1
- package/index.d.ts +35 -21
- package/lib/adapters/http.js +74 -14
- package/lib/adapters/xhr.js +65 -32
- package/lib/axios.js +6 -5
- package/lib/cancel/CancelToken.js +62 -0
- package/lib/core/Axios.js +60 -7
- package/lib/core/InterceptorManager.js +4 -2
- package/lib/core/README.md +1 -0
- package/lib/core/dispatchRequest.js +11 -3
- package/lib/core/enhanceError.js +2 -1
- package/lib/core/mergeConfig.js +50 -38
- package/lib/core/transformData.js +3 -1
- package/lib/defaults.js +48 -12
- package/lib/env/README.md +3 -0
- package/lib/env/data.js +3 -0
- package/lib/helpers/validator.js +82 -0
- package/lib/utils.js +1 -3
- package/package.json +23 -23
package/index.d.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
export interface AxiosTransformer {
|
2
|
-
(data: any, headers?:
|
2
|
+
(data: any, headers?: Record<string, string>): any;
|
3
3
|
}
|
4
4
|
|
5
5
|
export interface AxiosAdapter {
|
@@ -41,16 +41,22 @@ export type ResponseType =
|
|
41
41
|
| 'text'
|
42
42
|
| 'stream'
|
43
43
|
|
44
|
-
export interface
|
44
|
+
export interface TransitionalOptions{
|
45
|
+
silentJSONParsing: boolean;
|
46
|
+
forcedJSONParsing: boolean;
|
47
|
+
clarifyTimeoutError: boolean;
|
48
|
+
}
|
49
|
+
|
50
|
+
export interface AxiosRequestConfig<T = any> {
|
45
51
|
url?: string;
|
46
52
|
method?: Method;
|
47
53
|
baseURL?: string;
|
48
54
|
transformRequest?: AxiosTransformer | AxiosTransformer[];
|
49
55
|
transformResponse?: AxiosTransformer | AxiosTransformer[];
|
50
|
-
headers?:
|
56
|
+
headers?: Record<string, string>;
|
51
57
|
params?: any;
|
52
58
|
paramsSerializer?: (params: any) => string;
|
53
|
-
data?:
|
59
|
+
data?: T;
|
54
60
|
timeout?: number;
|
55
61
|
timeoutErrorMessage?: string;
|
56
62
|
withCredentials?: boolean;
|
@@ -71,18 +77,20 @@ export interface AxiosRequestConfig {
|
|
71
77
|
proxy?: AxiosProxyConfig | false;
|
72
78
|
cancelToken?: CancelToken;
|
73
79
|
decompress?: boolean;
|
80
|
+
transitional?: TransitionalOptions
|
81
|
+
signal?: AbortSignal;
|
74
82
|
}
|
75
83
|
|
76
|
-
export interface AxiosResponse<T =
|
84
|
+
export interface AxiosResponse<T = never> {
|
77
85
|
data: T;
|
78
86
|
status: number;
|
79
87
|
statusText: string;
|
80
|
-
headers:
|
81
|
-
config: AxiosRequestConfig
|
88
|
+
headers: Record<string, string>;
|
89
|
+
config: AxiosRequestConfig<T>;
|
82
90
|
request?: any;
|
83
91
|
}
|
84
92
|
|
85
|
-
export interface AxiosError<T =
|
93
|
+
export interface AxiosError<T = never> extends Error {
|
86
94
|
config: AxiosRequestConfig;
|
87
95
|
code?: string;
|
88
96
|
request?: any;
|
@@ -91,7 +99,7 @@ export interface AxiosError<T = any> extends Error {
|
|
91
99
|
toJSON: () => object;
|
92
100
|
}
|
93
101
|
|
94
|
-
export interface AxiosPromise<T =
|
102
|
+
export interface AxiosPromise<T = never> extends Promise<AxiosResponse<T>> {
|
95
103
|
}
|
96
104
|
|
97
105
|
export interface CancelStatic {
|
@@ -123,33 +131,39 @@ export interface CancelTokenSource {
|
|
123
131
|
}
|
124
132
|
|
125
133
|
export interface AxiosInterceptorManager<V> {
|
126
|
-
use(onFulfilled?: (value: V) =>
|
134
|
+
use<T = V>(onFulfilled?: (value: V) => T | Promise<T>, onRejected?: (error: any) => any): number;
|
127
135
|
eject(id: number): void;
|
128
136
|
}
|
129
137
|
|
130
|
-
export
|
131
|
-
(config
|
132
|
-
(url: string, config?: AxiosRequestConfig): AxiosPromise;
|
138
|
+
export class Axios {
|
139
|
+
constructor(config?: AxiosRequestConfig);
|
133
140
|
defaults: AxiosRequestConfig;
|
134
141
|
interceptors: {
|
135
142
|
request: AxiosInterceptorManager<AxiosRequestConfig>;
|
136
143
|
response: AxiosInterceptorManager<AxiosResponse>;
|
137
144
|
};
|
138
145
|
getUri(config?: AxiosRequestConfig): string;
|
139
|
-
request<T =
|
140
|
-
get<T =
|
141
|
-
delete<T =
|
142
|
-
head<T =
|
143
|
-
options<T =
|
144
|
-
post<T =
|
145
|
-
put<T =
|
146
|
-
patch<T =
|
146
|
+
request<T = never, R = AxiosResponse<T>> (config: AxiosRequestConfig<T>): Promise<R>;
|
147
|
+
get<T = never, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig<T>): Promise<R>;
|
148
|
+
delete<T = never, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig<T>): Promise<R>;
|
149
|
+
head<T = never, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig<T>): Promise<R>;
|
150
|
+
options<T = never, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig<T>): Promise<R>;
|
151
|
+
post<T = never, R = AxiosResponse<T>>(url: string, data?: T, config?: AxiosRequestConfig<T>): Promise<R>;
|
152
|
+
put<T = never, R = AxiosResponse<T>>(url: string, data?: T, config?: AxiosRequestConfig<T>): Promise<R>;
|
153
|
+
patch<T = never, R = AxiosResponse<T>>(url: string, data?: T, config?: AxiosRequestConfig<T>): Promise<R>;
|
154
|
+
}
|
155
|
+
|
156
|
+
export interface AxiosInstance extends Axios {
|
157
|
+
(config: AxiosRequestConfig): AxiosPromise;
|
158
|
+
(url: string, config?: AxiosRequestConfig): AxiosPromise;
|
147
159
|
}
|
148
160
|
|
149
161
|
export interface AxiosStatic extends AxiosInstance {
|
150
162
|
create(config?: AxiosRequestConfig): AxiosInstance;
|
151
163
|
Cancel: CancelStatic;
|
152
164
|
CancelToken: CancelTokenStatic;
|
165
|
+
Axios: typeof Axios;
|
166
|
+
readonly VERSION: string;
|
153
167
|
isCancel(value: any): boolean;
|
154
168
|
all<T>(values: (T | Promise<T>)[]): Promise<T[]>;
|
155
169
|
spread<T, R>(callback: (...args: T[]) => R): (array: T[]) => R;
|
package/lib/adapters/http.js
CHANGED
@@ -10,9 +10,11 @@ var httpFollow = require('follow-redirects').http;
|
|
10
10
|
var httpsFollow = require('follow-redirects').https;
|
11
11
|
var url = require('url');
|
12
12
|
var zlib = require('zlib');
|
13
|
-
var
|
13
|
+
var VERSION = require('./../env/data').version;
|
14
14
|
var createError = require('../core/createError');
|
15
15
|
var enhanceError = require('../core/enhanceError');
|
16
|
+
var defaults = require('../defaults');
|
17
|
+
var Cancel = require('../cancel/Cancel');
|
16
18
|
|
17
19
|
var isHttps = /https:?/;
|
18
20
|
|
@@ -44,20 +46,43 @@ function setProxy(options, proxy, location) {
|
|
44
46
|
/*eslint consistent-return:0*/
|
45
47
|
module.exports = function httpAdapter(config) {
|
46
48
|
return new Promise(function dispatchHttpRequest(resolvePromise, rejectPromise) {
|
49
|
+
var onCanceled;
|
50
|
+
function done() {
|
51
|
+
if (config.cancelToken) {
|
52
|
+
config.cancelToken.unsubscribe(onCanceled);
|
53
|
+
}
|
54
|
+
|
55
|
+
if (config.signal) {
|
56
|
+
config.signal.removeEventListener('abort', onCanceled);
|
57
|
+
}
|
58
|
+
}
|
47
59
|
var resolve = function resolve(value) {
|
60
|
+
done();
|
48
61
|
resolvePromise(value);
|
49
62
|
};
|
50
63
|
var reject = function reject(value) {
|
64
|
+
done();
|
51
65
|
rejectPromise(value);
|
52
66
|
};
|
53
67
|
var data = config.data;
|
54
68
|
var headers = config.headers;
|
69
|
+
var headerNames = {};
|
70
|
+
|
71
|
+
Object.keys(headers).forEach(function storeLowerName(name) {
|
72
|
+
headerNames[name.toLowerCase()] = name;
|
73
|
+
});
|
55
74
|
|
56
75
|
// Set User-Agent (required by some servers)
|
57
|
-
// Only set header if it hasn't been set in config
|
58
76
|
// See https://github.com/axios/axios/issues/69
|
59
|
-
if (
|
60
|
-
|
77
|
+
if ('user-agent' in headerNames) {
|
78
|
+
// User-Agent is specified; handle case where no UA header is desired
|
79
|
+
if (!headers[headerNames['user-agent']]) {
|
80
|
+
delete headers[headerNames['user-agent']];
|
81
|
+
}
|
82
|
+
// Otherwise, use specified value
|
83
|
+
} else {
|
84
|
+
// Only set header if it hasn't been set in config
|
85
|
+
headers['User-Agent'] = 'axios/' + VERSION;
|
61
86
|
}
|
62
87
|
|
63
88
|
if (data && !utils.isStream(data)) {
|
@@ -75,7 +100,9 @@ module.exports = function httpAdapter(config) {
|
|
75
100
|
}
|
76
101
|
|
77
102
|
// Add Content-Length header if data exists
|
78
|
-
|
103
|
+
if (!headerNames['content-length']) {
|
104
|
+
headers['Content-Length'] = data.length;
|
105
|
+
}
|
79
106
|
}
|
80
107
|
|
81
108
|
// HTTP basic authentication
|
@@ -98,8 +125,8 @@ module.exports = function httpAdapter(config) {
|
|
98
125
|
auth = urlUsername + ':' + urlPassword;
|
99
126
|
}
|
100
127
|
|
101
|
-
if (auth) {
|
102
|
-
delete headers.
|
128
|
+
if (auth && headerNames.authorization) {
|
129
|
+
delete headers[headerNames.authorization];
|
103
130
|
}
|
104
131
|
|
105
132
|
var isHttpsRequest = isHttps.test(protocol);
|
@@ -191,6 +218,10 @@ module.exports = function httpAdapter(config) {
|
|
191
218
|
options.maxBodyLength = config.maxBodyLength;
|
192
219
|
}
|
193
220
|
|
221
|
+
if (config.insecureHTTPParser) {
|
222
|
+
options.insecureHTTPParser = config.insecureHTTPParser;
|
223
|
+
}
|
224
|
+
|
194
225
|
// Create the request
|
195
226
|
var req = transport.request(options, function handleResponse(res) {
|
196
227
|
if (req.aborted) return;
|
@@ -231,11 +262,13 @@ module.exports = function httpAdapter(config) {
|
|
231
262
|
settle(resolve, reject, response);
|
232
263
|
} else {
|
233
264
|
var responseBuffer = [];
|
265
|
+
var totalResponseBytes = 0;
|
234
266
|
stream.on('data', function handleStreamData(chunk) {
|
235
267
|
responseBuffer.push(chunk);
|
268
|
+
totalResponseBytes += chunk.length;
|
236
269
|
|
237
270
|
// make sure the content length is not over the maxContentLength if specified
|
238
|
-
if (config.maxContentLength > -1 &&
|
271
|
+
if (config.maxContentLength > -1 && totalResponseBytes > config.maxContentLength) {
|
239
272
|
stream.destroy();
|
240
273
|
reject(createError('maxContentLength size of ' + config.maxContentLength + ' exceeded',
|
241
274
|
config, null, lastRequest));
|
@@ -270,27 +303,54 @@ module.exports = function httpAdapter(config) {
|
|
270
303
|
|
271
304
|
// Handle request timeout
|
272
305
|
if (config.timeout) {
|
306
|
+
// This is forcing a int timeout to avoid problems if the `req` interface doesn't handle other types.
|
307
|
+
var timeout = parseInt(config.timeout, 10);
|
308
|
+
|
309
|
+
if (isNaN(timeout)) {
|
310
|
+
reject(createError(
|
311
|
+
'error trying to parse `config.timeout` to int',
|
312
|
+
config,
|
313
|
+
'ERR_PARSE_TIMEOUT',
|
314
|
+
req
|
315
|
+
));
|
316
|
+
|
317
|
+
return;
|
318
|
+
}
|
319
|
+
|
273
320
|
// Sometime, the response will be very slow, and does not respond, the connect event will be block by event loop system.
|
274
321
|
// And timer callback will be fired, and abort() will be invoked before connection, then get "socket hang up" and code ECONNRESET.
|
275
322
|
// At this time, if we have a large number of request, nodejs will hang up some socket on background. and the number will up and up.
|
276
323
|
// And then these socket which be hang up will devoring CPU little by little.
|
277
324
|
// ClientRequest.setTimeout will be fired on the specify milliseconds, and can make sure that abort() will be fired after connect.
|
278
|
-
req.setTimeout(
|
325
|
+
req.setTimeout(timeout, function handleRequestTimeout() {
|
279
326
|
req.abort();
|
280
|
-
|
327
|
+
var transitional = config.transitional || defaults.transitional;
|
328
|
+
reject(createError(
|
329
|
+
'timeout of ' + timeout + 'ms exceeded',
|
330
|
+
config,
|
331
|
+
transitional.clarifyTimeoutError ? 'ETIMEDOUT' : 'ECONNABORTED',
|
332
|
+
req
|
333
|
+
));
|
281
334
|
});
|
282
335
|
}
|
283
336
|
|
284
|
-
if (config.cancelToken) {
|
337
|
+
if (config.cancelToken || config.signal) {
|
285
338
|
// Handle cancellation
|
286
|
-
|
339
|
+
// eslint-disable-next-line func-names
|
340
|
+
onCanceled = function(cancel) {
|
287
341
|
if (req.aborted) return;
|
288
342
|
|
289
343
|
req.abort();
|
290
|
-
reject(cancel);
|
291
|
-
}
|
344
|
+
reject(!cancel || (cancel && cancel.type) ? new Cancel('canceled') : cancel);
|
345
|
+
};
|
346
|
+
|
347
|
+
config.cancelToken && config.cancelToken.subscribe(onCanceled);
|
348
|
+
if (config.signal) {
|
349
|
+
config.signal.aborted ? onCanceled() : config.signal.addEventListener('abort', onCanceled);
|
350
|
+
}
|
292
351
|
}
|
293
352
|
|
353
|
+
|
294
354
|
// Send the request
|
295
355
|
if (utils.isStream(data)) {
|
296
356
|
data.on('error', function handleStreamError(err) {
|
package/lib/adapters/xhr.js
CHANGED
@@ -8,11 +8,24 @@ var buildFullPath = require('../core/buildFullPath');
|
|
8
8
|
var parseHeaders = require('./../helpers/parseHeaders');
|
9
9
|
var isURLSameOrigin = require('./../helpers/isURLSameOrigin');
|
10
10
|
var createError = require('../core/createError');
|
11
|
+
var defaults = require('../defaults');
|
12
|
+
var Cancel = require('../cancel/Cancel');
|
11
13
|
|
12
14
|
module.exports = function xhrAdapter(config) {
|
13
15
|
return new Promise(function dispatchXhrRequest(resolve, reject) {
|
14
16
|
var requestData = config.data;
|
15
17
|
var requestHeaders = config.headers;
|
18
|
+
var responseType = config.responseType;
|
19
|
+
var onCanceled;
|
20
|
+
function done() {
|
21
|
+
if (config.cancelToken) {
|
22
|
+
config.cancelToken.unsubscribe(onCanceled);
|
23
|
+
}
|
24
|
+
|
25
|
+
if (config.signal) {
|
26
|
+
config.signal.removeEventListener('abort', onCanceled);
|
27
|
+
}
|
28
|
+
}
|
16
29
|
|
17
30
|
if (utils.isFormData(requestData)) {
|
18
31
|
delete requestHeaders['Content-Type']; // Let the browser set it
|
@@ -33,23 +46,14 @@ module.exports = function xhrAdapter(config) {
|
|
33
46
|
// Set the request timeout in MS
|
34
47
|
request.timeout = config.timeout;
|
35
48
|
|
36
|
-
|
37
|
-
|
38
|
-
if (!request || request.readyState !== 4) {
|
39
|
-
return;
|
40
|
-
}
|
41
|
-
|
42
|
-
// The request errored out and we didn't get a response, this will be
|
43
|
-
// handled by onerror instead
|
44
|
-
// With one exception: request that using file: protocol, most browsers
|
45
|
-
// will return status as 0 even though it's a successful request
|
46
|
-
if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) {
|
49
|
+
function onloadend() {
|
50
|
+
if (!request) {
|
47
51
|
return;
|
48
52
|
}
|
49
|
-
|
50
53
|
// Prepare the response
|
51
54
|
var responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null;
|
52
|
-
var responseData = !
|
55
|
+
var responseData = !responseType || responseType === 'text' || responseType === 'json' ?
|
56
|
+
request.responseText : request.response;
|
53
57
|
var response = {
|
54
58
|
data: responseData,
|
55
59
|
status: request.status,
|
@@ -59,11 +63,40 @@ module.exports = function xhrAdapter(config) {
|
|
59
63
|
request: request
|
60
64
|
};
|
61
65
|
|
62
|
-
settle(
|
66
|
+
settle(function _resolve(value) {
|
67
|
+
resolve(value);
|
68
|
+
done();
|
69
|
+
}, function _reject(err) {
|
70
|
+
reject(err);
|
71
|
+
done();
|
72
|
+
}, response);
|
63
73
|
|
64
74
|
// Clean up request
|
65
75
|
request = null;
|
66
|
-
}
|
76
|
+
}
|
77
|
+
|
78
|
+
if ('onloadend' in request) {
|
79
|
+
// Use onloadend if available
|
80
|
+
request.onloadend = onloadend;
|
81
|
+
} else {
|
82
|
+
// Listen for ready state to emulate onloadend
|
83
|
+
request.onreadystatechange = function handleLoad() {
|
84
|
+
if (!request || request.readyState !== 4) {
|
85
|
+
return;
|
86
|
+
}
|
87
|
+
|
88
|
+
// The request errored out and we didn't get a response, this will be
|
89
|
+
// handled by onerror instead
|
90
|
+
// With one exception: request that using file: protocol, most browsers
|
91
|
+
// will return status as 0 even though it's a successful request
|
92
|
+
if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) {
|
93
|
+
return;
|
94
|
+
}
|
95
|
+
// readystate handler is calling before onerror or ontimeout handlers,
|
96
|
+
// so we should call onloadend on the next 'tick'
|
97
|
+
setTimeout(onloadend);
|
98
|
+
};
|
99
|
+
}
|
67
100
|
|
68
101
|
// Handle browser request cancellation (as opposed to a manual cancellation)
|
69
102
|
request.onabort = function handleAbort() {
|
@@ -90,10 +123,14 @@ module.exports = function xhrAdapter(config) {
|
|
90
123
|
// Handle timeout
|
91
124
|
request.ontimeout = function handleTimeout() {
|
92
125
|
var timeoutErrorMessage = 'timeout of ' + config.timeout + 'ms exceeded';
|
126
|
+
var transitional = config.transitional || defaults.transitional;
|
93
127
|
if (config.timeoutErrorMessage) {
|
94
128
|
timeoutErrorMessage = config.timeoutErrorMessage;
|
95
129
|
}
|
96
|
-
reject(createError(
|
130
|
+
reject(createError(
|
131
|
+
timeoutErrorMessage,
|
132
|
+
config,
|
133
|
+
transitional.clarifyTimeoutError ? 'ETIMEDOUT' : 'ECONNABORTED',
|
97
134
|
request));
|
98
135
|
|
99
136
|
// Clean up request
|
@@ -133,16 +170,8 @@ module.exports = function xhrAdapter(config) {
|
|
133
170
|
}
|
134
171
|
|
135
172
|
// Add responseType to request if needed
|
136
|
-
if (
|
137
|
-
|
138
|
-
request.responseType = config.responseType;
|
139
|
-
} catch (e) {
|
140
|
-
// Expected DOMException thrown by browsers not compatible XMLHttpRequest Level 2.
|
141
|
-
// But, this can be suppressed for 'json' type as it can be parsed by default 'transformResponse' function.
|
142
|
-
if (config.responseType !== 'json') {
|
143
|
-
throw e;
|
144
|
-
}
|
145
|
-
}
|
173
|
+
if (responseType && responseType !== 'json') {
|
174
|
+
request.responseType = config.responseType;
|
146
175
|
}
|
147
176
|
|
148
177
|
// Handle progress if needed
|
@@ -155,18 +184,22 @@ module.exports = function xhrAdapter(config) {
|
|
155
184
|
request.upload.addEventListener('progress', config.onUploadProgress);
|
156
185
|
}
|
157
186
|
|
158
|
-
if (config.cancelToken) {
|
187
|
+
if (config.cancelToken || config.signal) {
|
159
188
|
// Handle cancellation
|
160
|
-
|
189
|
+
// eslint-disable-next-line func-names
|
190
|
+
onCanceled = function(cancel) {
|
161
191
|
if (!request) {
|
162
192
|
return;
|
163
193
|
}
|
164
|
-
|
194
|
+
reject(!cancel || (cancel && cancel.type) ? new Cancel('canceled') : cancel);
|
165
195
|
request.abort();
|
166
|
-
reject(cancel);
|
167
|
-
// Clean up request
|
168
196
|
request = null;
|
169
|
-
}
|
197
|
+
};
|
198
|
+
|
199
|
+
config.cancelToken && config.cancelToken.subscribe(onCanceled);
|
200
|
+
if (config.signal) {
|
201
|
+
config.signal.aborted ? onCanceled() : config.signal.addEventListener('abort', onCanceled);
|
202
|
+
}
|
170
203
|
}
|
171
204
|
|
172
205
|
if (!requestData) {
|
package/lib/axios.js
CHANGED
@@ -22,6 +22,11 @@ function createInstance(defaultConfig) {
|
|
22
22
|
// Copy context to instance
|
23
23
|
utils.extend(instance, context);
|
24
24
|
|
25
|
+
// Factory for creating new instances
|
26
|
+
instance.create = function create(instanceConfig) {
|
27
|
+
return createInstance(mergeConfig(defaultConfig, instanceConfig));
|
28
|
+
};
|
29
|
+
|
25
30
|
return instance;
|
26
31
|
}
|
27
32
|
|
@@ -31,15 +36,11 @@ var axios = createInstance(defaults);
|
|
31
36
|
// Expose Axios class to allow class inheritance
|
32
37
|
axios.Axios = Axios;
|
33
38
|
|
34
|
-
// Factory for creating new instances
|
35
|
-
axios.create = function create(instanceConfig) {
|
36
|
-
return createInstance(mergeConfig(axios.defaults, instanceConfig));
|
37
|
-
};
|
38
|
-
|
39
39
|
// Expose Cancel & CancelToken
|
40
40
|
axios.Cancel = require('./cancel/Cancel');
|
41
41
|
axios.CancelToken = require('./cancel/CancelToken');
|
42
42
|
axios.isCancel = require('./cancel/isCancel');
|
43
|
+
axios.VERSION = require('./env/data').version;
|
43
44
|
|
44
45
|
// Expose all/spread
|
45
46
|
axios.all = function all(promises) {
|
@@ -14,11 +14,42 @@ function CancelToken(executor) {
|
|
14
14
|
}
|
15
15
|
|
16
16
|
var resolvePromise;
|
17
|
+
|
17
18
|
this.promise = new Promise(function promiseExecutor(resolve) {
|
18
19
|
resolvePromise = resolve;
|
19
20
|
});
|
20
21
|
|
21
22
|
var token = this;
|
23
|
+
|
24
|
+
// eslint-disable-next-line func-names
|
25
|
+
this.promise.then(function(cancel) {
|
26
|
+
if (!token._listeners) return;
|
27
|
+
|
28
|
+
var i;
|
29
|
+
var l = token._listeners.length;
|
30
|
+
|
31
|
+
for (i = 0; i < l; i++) {
|
32
|
+
token._listeners[i](cancel);
|
33
|
+
}
|
34
|
+
token._listeners = null;
|
35
|
+
});
|
36
|
+
|
37
|
+
// eslint-disable-next-line func-names
|
38
|
+
this.promise.then = function(onfulfilled) {
|
39
|
+
var _resolve;
|
40
|
+
// eslint-disable-next-line func-names
|
41
|
+
var promise = new Promise(function(resolve) {
|
42
|
+
token.subscribe(resolve);
|
43
|
+
_resolve = resolve;
|
44
|
+
}).then(onfulfilled);
|
45
|
+
|
46
|
+
promise.cancel = function reject() {
|
47
|
+
token.unsubscribe(_resolve);
|
48
|
+
};
|
49
|
+
|
50
|
+
return promise;
|
51
|
+
};
|
52
|
+
|
22
53
|
executor(function cancel(message) {
|
23
54
|
if (token.reason) {
|
24
55
|
// Cancellation has already been requested
|
@@ -39,6 +70,37 @@ CancelToken.prototype.throwIfRequested = function throwIfRequested() {
|
|
39
70
|
}
|
40
71
|
};
|
41
72
|
|
73
|
+
/**
|
74
|
+
* Subscribe to the cancel signal
|
75
|
+
*/
|
76
|
+
|
77
|
+
CancelToken.prototype.subscribe = function subscribe(listener) {
|
78
|
+
if (this.reason) {
|
79
|
+
listener(this.reason);
|
80
|
+
return;
|
81
|
+
}
|
82
|
+
|
83
|
+
if (this._listeners) {
|
84
|
+
this._listeners.push(listener);
|
85
|
+
} else {
|
86
|
+
this._listeners = [listener];
|
87
|
+
}
|
88
|
+
};
|
89
|
+
|
90
|
+
/**
|
91
|
+
* Unsubscribe from the cancel signal
|
92
|
+
*/
|
93
|
+
|
94
|
+
CancelToken.prototype.unsubscribe = function unsubscribe(listener) {
|
95
|
+
if (!this._listeners) {
|
96
|
+
return;
|
97
|
+
}
|
98
|
+
var index = this._listeners.indexOf(listener);
|
99
|
+
if (index !== -1) {
|
100
|
+
this._listeners.splice(index, 1);
|
101
|
+
}
|
102
|
+
};
|
103
|
+
|
42
104
|
/**
|
43
105
|
* Returns an object that contains a new `CancelToken` and a function that, when called,
|
44
106
|
* cancels the `CancelToken`.
|
package/lib/core/Axios.js
CHANGED
@@ -5,7 +5,9 @@ var buildURL = require('../helpers/buildURL');
|
|
5
5
|
var InterceptorManager = require('./InterceptorManager');
|
6
6
|
var dispatchRequest = require('./dispatchRequest');
|
7
7
|
var mergeConfig = require('./mergeConfig');
|
8
|
+
var validator = require('../helpers/validator');
|
8
9
|
|
10
|
+
var validators = validator.validators;
|
9
11
|
/**
|
10
12
|
* Create a new instance of Axios
|
11
13
|
*
|
@@ -45,20 +47,71 @@ Axios.prototype.request = function request(config) {
|
|
45
47
|
config.method = 'get';
|
46
48
|
}
|
47
49
|
|
48
|
-
|
49
|
-
var chain = [dispatchRequest, undefined];
|
50
|
-
var promise = Promise.resolve(config);
|
50
|
+
var transitional = config.transitional;
|
51
51
|
|
52
|
+
if (transitional !== undefined) {
|
53
|
+
validator.assertOptions(transitional, {
|
54
|
+
silentJSONParsing: validators.transitional(validators.boolean),
|
55
|
+
forcedJSONParsing: validators.transitional(validators.boolean),
|
56
|
+
clarifyTimeoutError: validators.transitional(validators.boolean)
|
57
|
+
}, false);
|
58
|
+
}
|
59
|
+
|
60
|
+
// filter out skipped interceptors
|
61
|
+
var requestInterceptorChain = [];
|
62
|
+
var synchronousRequestInterceptors = true;
|
52
63
|
this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
|
53
|
-
|
64
|
+
if (typeof interceptor.runWhen === 'function' && interceptor.runWhen(config) === false) {
|
65
|
+
return;
|
66
|
+
}
|
67
|
+
|
68
|
+
synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous;
|
69
|
+
|
70
|
+
requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);
|
54
71
|
});
|
55
72
|
|
73
|
+
var responseInterceptorChain = [];
|
56
74
|
this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
|
57
|
-
|
75
|
+
responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected);
|
58
76
|
});
|
59
77
|
|
60
|
-
|
61
|
-
|
78
|
+
var promise;
|
79
|
+
|
80
|
+
if (!synchronousRequestInterceptors) {
|
81
|
+
var chain = [dispatchRequest, undefined];
|
82
|
+
|
83
|
+
Array.prototype.unshift.apply(chain, requestInterceptorChain);
|
84
|
+
chain = chain.concat(responseInterceptorChain);
|
85
|
+
|
86
|
+
promise = Promise.resolve(config);
|
87
|
+
while (chain.length) {
|
88
|
+
promise = promise.then(chain.shift(), chain.shift());
|
89
|
+
}
|
90
|
+
|
91
|
+
return promise;
|
92
|
+
}
|
93
|
+
|
94
|
+
|
95
|
+
var newConfig = config;
|
96
|
+
while (requestInterceptorChain.length) {
|
97
|
+
var onFulfilled = requestInterceptorChain.shift();
|
98
|
+
var onRejected = requestInterceptorChain.shift();
|
99
|
+
try {
|
100
|
+
newConfig = onFulfilled(newConfig);
|
101
|
+
} catch (error) {
|
102
|
+
onRejected(error);
|
103
|
+
break;
|
104
|
+
}
|
105
|
+
}
|
106
|
+
|
107
|
+
try {
|
108
|
+
promise = dispatchRequest(newConfig);
|
109
|
+
} catch (error) {
|
110
|
+
return Promise.reject(error);
|
111
|
+
}
|
112
|
+
|
113
|
+
while (responseInterceptorChain.length) {
|
114
|
+
promise = promise.then(responseInterceptorChain.shift(), responseInterceptorChain.shift());
|
62
115
|
}
|
63
116
|
|
64
117
|
return promise;
|
@@ -14,10 +14,12 @@ function InterceptorManager() {
|
|
14
14
|
*
|
15
15
|
* @return {Number} An ID used to remove interceptor later
|
16
16
|
*/
|
17
|
-
InterceptorManager.prototype.use = function use(fulfilled, rejected) {
|
17
|
+
InterceptorManager.prototype.use = function use(fulfilled, rejected, options) {
|
18
18
|
this.handlers.push({
|
19
19
|
fulfilled: fulfilled,
|
20
|
-
rejected: rejected
|
20
|
+
rejected: rejected,
|
21
|
+
synchronous: options ? options.synchronous : false,
|
22
|
+
runWhen: options ? options.runWhen : null
|
21
23
|
});
|
22
24
|
return this.handlers.length - 1;
|
23
25
|
};
|
package/lib/core/README.md
CHANGED
@@ -3,5 +3,6 @@
|
|
3
3
|
The modules found in `core/` should be modules that are specific to the domain logic of axios. These modules would most likely not make sense to be consumed outside of the axios module, as their logic is too specific. Some examples of core modules are:
|
4
4
|
|
5
5
|
- Dispatching requests
|
6
|
+
- Requests sent via `adapters/` (see lib/adapters/README.md)
|
6
7
|
- Managing interceptors
|
7
8
|
- Handling config
|