axios 1.7.9 → 1.12.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.
@@ -8,14 +8,18 @@ import {progressEventReducer, progressEventDecorator, asyncDecorator} from "../h
8
8
  import resolveConfig from "../helpers/resolveConfig.js";
9
9
  import settle from "../core/settle.js";
10
10
 
11
- const isFetchSupported = typeof fetch === 'function' && typeof Request === 'function' && typeof Response === 'function';
12
- const isReadableStreamSupported = isFetchSupported && typeof ReadableStream === 'function';
11
+ const DEFAULT_CHUNK_SIZE = 64 * 1024;
12
+
13
+ const {isFunction} = utils;
14
+
15
+ const globalFetchAPI = (({fetch, Request, Response}) => ({
16
+ fetch, Request, Response
17
+ }))(utils.global);
18
+
19
+ const {
20
+ ReadableStream, TextEncoder
21
+ } = utils.global;
13
22
 
14
- // used only inside the fetch adapter
15
- const encodeText = isFetchSupported && (typeof TextEncoder === 'function' ?
16
- ((encoder) => (str) => encoder.encode(str))(new TextEncoder()) :
17
- async (str) => new Uint8Array(await new Response(str).arrayBuffer())
18
- );
19
23
 
20
24
  const test = (fn, ...args) => {
21
25
  try {
@@ -25,205 +29,258 @@ const test = (fn, ...args) => {
25
29
  }
26
30
  }
27
31
 
28
- const supportsRequestStream = isReadableStreamSupported && test(() => {
29
- let duplexAccessed = false;
32
+ const factory = (env) => {
33
+ const {fetch, Request, Response} = Object.assign({}, globalFetchAPI, env);
34
+ const isFetchSupported = isFunction(fetch);
35
+ const isRequestSupported = isFunction(Request);
36
+ const isResponseSupported = isFunction(Response);
30
37
 
31
- const hasContentType = new Request(platform.origin, {
32
- body: new ReadableStream(),
33
- method: 'POST',
34
- get duplex() {
35
- duplexAccessed = true;
36
- return 'half';
37
- },
38
- }).headers.has('Content-Type');
38
+ if (!isFetchSupported) {
39
+ return false;
40
+ }
39
41
 
40
- return duplexAccessed && !hasContentType;
41
- });
42
+ const isReadableStreamSupported = isFetchSupported && isFunction(ReadableStream);
42
43
 
43
- const DEFAULT_CHUNK_SIZE = 64 * 1024;
44
+ const encodeText = isFetchSupported && (typeof TextEncoder === 'function' ?
45
+ ((encoder) => (str) => encoder.encode(str))(new TextEncoder()) :
46
+ async (str) => new Uint8Array(await new Request(str).arrayBuffer())
47
+ );
44
48
 
45
- const supportsResponseStream = isReadableStreamSupported &&
46
- test(() => utils.isReadableStream(new Response('').body));
49
+ const supportsRequestStream = isRequestSupported && isReadableStreamSupported && test(() => {
50
+ let duplexAccessed = false;
47
51
 
52
+ const hasContentType = new Request(platform.origin, {
53
+ body: new ReadableStream(),
54
+ method: 'POST',
55
+ get duplex() {
56
+ duplexAccessed = true;
57
+ return 'half';
58
+ },
59
+ }).headers.has('Content-Type');
48
60
 
49
- const resolvers = {
50
- stream: supportsResponseStream && ((res) => res.body)
51
- };
61
+ return duplexAccessed && !hasContentType;
62
+ });
63
+
64
+ const supportsResponseStream = isResponseSupported && isReadableStreamSupported &&
65
+ test(() => utils.isReadableStream(new Response('').body));
66
+
67
+ const resolvers = {
68
+ stream: supportsResponseStream && ((res) => res.body)
69
+ };
70
+
71
+ isFetchSupported && ((() => {
72
+ ['text', 'arrayBuffer', 'blob', 'formData', 'stream'].forEach(type => {
73
+ !resolvers[type] && (resolvers[type] = (res, config) => {
74
+ let method = res && res[type];
75
+
76
+ if (method) {
77
+ return method.call(res);
78
+ }
52
79
 
53
- isFetchSupported && (((res) => {
54
- ['text', 'arrayBuffer', 'blob', 'formData', 'stream'].forEach(type => {
55
- !resolvers[type] && (resolvers[type] = utils.isFunction(res[type]) ? (res) => res[type]() :
56
- (_, config) => {
57
80
  throw new AxiosError(`Response type '${type}' is not supported`, AxiosError.ERR_NOT_SUPPORT, config);
58
81
  })
59
- });
60
- })(new Response));
82
+ });
83
+ })());
61
84
 
62
- const getBodyLength = async (body) => {
63
- if (body == null) {
64
- return 0;
65
- }
85
+ const getBodyLength = async (body) => {
86
+ if (body == null) {
87
+ return 0;
88
+ }
66
89
 
67
- if(utils.isBlob(body)) {
68
- return body.size;
69
- }
90
+ if (utils.isBlob(body)) {
91
+ return body.size;
92
+ }
70
93
 
71
- if(utils.isSpecCompliantForm(body)) {
72
- const _request = new Request(platform.origin, {
73
- method: 'POST',
74
- body,
75
- });
76
- return (await _request.arrayBuffer()).byteLength;
77
- }
94
+ if (utils.isSpecCompliantForm(body)) {
95
+ const _request = new Request(platform.origin, {
96
+ method: 'POST',
97
+ body,
98
+ });
99
+ return (await _request.arrayBuffer()).byteLength;
100
+ }
78
101
 
79
- if(utils.isArrayBufferView(body) || utils.isArrayBuffer(body)) {
80
- return body.byteLength;
81
- }
102
+ if (utils.isArrayBufferView(body) || utils.isArrayBuffer(body)) {
103
+ return body.byteLength;
104
+ }
82
105
 
83
- if(utils.isURLSearchParams(body)) {
84
- body = body + '';
85
- }
106
+ if (utils.isURLSearchParams(body)) {
107
+ body = body + '';
108
+ }
86
109
 
87
- if(utils.isString(body)) {
88
- return (await encodeText(body)).byteLength;
110
+ if (utils.isString(body)) {
111
+ return (await encodeText(body)).byteLength;
112
+ }
89
113
  }
90
- }
91
114
 
92
- const resolveBodyLength = async (headers, body) => {
93
- const length = utils.toFiniteNumber(headers.getContentLength());
115
+ const resolveBodyLength = async (headers, body) => {
116
+ const length = utils.toFiniteNumber(headers.getContentLength());
94
117
 
95
- return length == null ? getBodyLength(body) : length;
96
- }
118
+ return length == null ? getBodyLength(body) : length;
119
+ }
97
120
 
98
- export default isFetchSupported && (async (config) => {
99
- let {
100
- url,
101
- method,
102
- data,
103
- signal,
104
- cancelToken,
105
- timeout,
106
- onDownloadProgress,
107
- onUploadProgress,
108
- responseType,
109
- headers,
110
- withCredentials = 'same-origin',
111
- fetchOptions
112
- } = resolveConfig(config);
113
-
114
- responseType = responseType ? (responseType + '').toLowerCase() : 'text';
115
-
116
- let composedSignal = composeSignals([signal, cancelToken && cancelToken.toAbortSignal()], timeout);
117
-
118
- let request;
119
-
120
- const unsubscribe = composedSignal && composedSignal.unsubscribe && (() => {
121
+ return async (config) => {
122
+ let {
123
+ url,
124
+ method,
125
+ data,
126
+ signal,
127
+ cancelToken,
128
+ timeout,
129
+ onDownloadProgress,
130
+ onUploadProgress,
131
+ responseType,
132
+ headers,
133
+ withCredentials = 'same-origin',
134
+ fetchOptions
135
+ } = resolveConfig(config);
136
+
137
+ responseType = responseType ? (responseType + '').toLowerCase() : 'text';
138
+
139
+ let composedSignal = composeSignals([signal, cancelToken && cancelToken.toAbortSignal()], timeout);
140
+
141
+ let request = null;
142
+
143
+ const unsubscribe = composedSignal && composedSignal.unsubscribe && (() => {
121
144
  composedSignal.unsubscribe();
122
- });
145
+ });
123
146
 
124
- let requestContentLength;
147
+ let requestContentLength;
125
148
 
126
- try {
127
- if (
128
- onUploadProgress && supportsRequestStream && method !== 'get' && method !== 'head' &&
129
- (requestContentLength = await resolveBodyLength(headers, data)) !== 0
130
- ) {
131
- let _request = new Request(url, {
132
- method: 'POST',
133
- body: data,
134
- duplex: "half"
135
- });
149
+ try {
150
+ if (
151
+ onUploadProgress && supportsRequestStream && method !== 'get' && method !== 'head' &&
152
+ (requestContentLength = await resolveBodyLength(headers, data)) !== 0
153
+ ) {
154
+ let _request = new Request(url, {
155
+ method: 'POST',
156
+ body: data,
157
+ duplex: "half"
158
+ });
136
159
 
137
- let contentTypeHeader;
160
+ let contentTypeHeader;
138
161
 
139
- if (utils.isFormData(data) && (contentTypeHeader = _request.headers.get('content-type'))) {
140
- headers.setContentType(contentTypeHeader)
141
- }
162
+ if (utils.isFormData(data) && (contentTypeHeader = _request.headers.get('content-type'))) {
163
+ headers.setContentType(contentTypeHeader)
164
+ }
142
165
 
143
- if (_request.body) {
144
- const [onProgress, flush] = progressEventDecorator(
145
- requestContentLength,
146
- progressEventReducer(asyncDecorator(onUploadProgress))
147
- );
166
+ if (_request.body) {
167
+ const [onProgress, flush] = progressEventDecorator(
168
+ requestContentLength,
169
+ progressEventReducer(asyncDecorator(onUploadProgress))
170
+ );
148
171
 
149
- data = trackStream(_request.body, DEFAULT_CHUNK_SIZE, onProgress, flush);
172
+ data = trackStream(_request.body, DEFAULT_CHUNK_SIZE, onProgress, flush);
173
+ }
150
174
  }
151
- }
152
175
 
153
- if (!utils.isString(withCredentials)) {
154
- withCredentials = withCredentials ? 'include' : 'omit';
155
- }
176
+ if (!utils.isString(withCredentials)) {
177
+ withCredentials = withCredentials ? 'include' : 'omit';
178
+ }
156
179
 
157
- // Cloudflare Workers throws when credentials are defined
158
- // see https://github.com/cloudflare/workerd/issues/902
159
- const isCredentialsSupported = "credentials" in Request.prototype;
160
- request = new Request(url, {
161
- ...fetchOptions,
162
- signal: composedSignal,
163
- method: method.toUpperCase(),
164
- headers: headers.normalize().toJSON(),
165
- body: data,
166
- duplex: "half",
167
- credentials: isCredentialsSupported ? withCredentials : undefined
168
- });
180
+ // Cloudflare Workers throws when credentials are defined
181
+ // see https://github.com/cloudflare/workerd/issues/902
182
+ const isCredentialsSupported = isRequestSupported && "credentials" in Request.prototype;
169
183
 
170
- let response = await fetch(request);
184
+ const resolvedOptions = {
185
+ ...fetchOptions,
186
+ signal: composedSignal,
187
+ method: method.toUpperCase(),
188
+ headers: headers.normalize().toJSON(),
189
+ body: data,
190
+ duplex: "half",
191
+ credentials: isCredentialsSupported ? withCredentials : undefined
192
+ };
171
193
 
172
- const isStreamResponse = supportsResponseStream && (responseType === 'stream' || responseType === 'response');
194
+ request = isRequestSupported && new Request(url, resolvedOptions);
173
195
 
174
- if (supportsResponseStream && (onDownloadProgress || (isStreamResponse && unsubscribe))) {
175
- const options = {};
196
+ let response = await (isRequestSupported ? fetch(request, fetchOptions) : fetch(url, resolvedOptions));
176
197
 
177
- ['status', 'statusText', 'headers'].forEach(prop => {
178
- options[prop] = response[prop];
179
- });
198
+ const isStreamResponse = supportsResponseStream && (responseType === 'stream' || responseType === 'response');
180
199
 
181
- const responseContentLength = utils.toFiniteNumber(response.headers.get('content-length'));
200
+ if (supportsResponseStream && (onDownloadProgress || (isStreamResponse && unsubscribe))) {
201
+ const options = {};
182
202
 
183
- const [onProgress, flush] = onDownloadProgress && progressEventDecorator(
184
- responseContentLength,
185
- progressEventReducer(asyncDecorator(onDownloadProgress), true)
186
- ) || [];
203
+ ['status', 'statusText', 'headers'].forEach(prop => {
204
+ options[prop] = response[prop];
205
+ });
187
206
 
188
- response = new Response(
189
- trackStream(response.body, DEFAULT_CHUNK_SIZE, onProgress, () => {
190
- flush && flush();
191
- unsubscribe && unsubscribe();
192
- }),
193
- options
194
- );
195
- }
207
+ const responseContentLength = utils.toFiniteNumber(response.headers.get('content-length'));
208
+
209
+ const [onProgress, flush] = onDownloadProgress && progressEventDecorator(
210
+ responseContentLength,
211
+ progressEventReducer(asyncDecorator(onDownloadProgress), true)
212
+ ) || [];
196
213
 
197
- responseType = responseType || 'text';
214
+ response = new Response(
215
+ trackStream(response.body, DEFAULT_CHUNK_SIZE, onProgress, () => {
216
+ flush && flush();
217
+ unsubscribe && unsubscribe();
218
+ }),
219
+ options
220
+ );
221
+ }
222
+
223
+ responseType = responseType || 'text';
198
224
 
199
- let responseData = await resolvers[utils.findKey(resolvers, responseType) || 'text'](response, config);
225
+ let responseData = await resolvers[utils.findKey(resolvers, responseType) || 'text'](response, config);
200
226
 
201
- !isStreamResponse && unsubscribe && unsubscribe();
227
+ !isStreamResponse && unsubscribe && unsubscribe();
202
228
 
203
- return await new Promise((resolve, reject) => {
204
- settle(resolve, reject, {
205
- data: responseData,
206
- headers: AxiosHeaders.from(response.headers),
207
- status: response.status,
208
- statusText: response.statusText,
209
- config,
210
- request
229
+ return await new Promise((resolve, reject) => {
230
+ settle(resolve, reject, {
231
+ data: responseData,
232
+ headers: AxiosHeaders.from(response.headers),
233
+ status: response.status,
234
+ statusText: response.statusText,
235
+ config,
236
+ request
237
+ })
211
238
  })
212
- })
213
- } catch (err) {
214
- unsubscribe && unsubscribe();
215
-
216
- if (err && err.name === 'TypeError' && /fetch/i.test(err.message)) {
217
- throw Object.assign(
218
- new AxiosError('Network Error', AxiosError.ERR_NETWORK, config, request),
219
- {
220
- cause: err.cause || err
221
- }
222
- )
239
+ } catch (err) {
240
+ unsubscribe && unsubscribe();
241
+
242
+ if (err && err.name === 'TypeError' && /Load failed|fetch/i.test(err.message)) {
243
+ throw Object.assign(
244
+ new AxiosError('Network Error', AxiosError.ERR_NETWORK, config, request),
245
+ {
246
+ cause: err.cause || err
247
+ }
248
+ )
249
+ }
250
+
251
+ throw AxiosError.from(err, err && err.code, config, request);
223
252
  }
253
+ }
254
+ }
255
+
256
+ const seedCache = new Map();
224
257
 
225
- throw AxiosError.from(err, err && err.code, config, request);
258
+ export const getFetch = (config) => {
259
+ let env = utils.merge.call({
260
+ skipUndefined: true
261
+ }, globalFetchAPI, config ? config.env : null);
262
+
263
+ const {fetch, Request, Response} = env;
264
+
265
+ const seeds = [
266
+ Request, Response, fetch
267
+ ];
268
+
269
+ let len = seeds.length, i = len,
270
+ seed, target, map = seedCache;
271
+
272
+ while (i--) {
273
+ seed = seeds[i];
274
+ target = map.get(seed);
275
+
276
+ target === undefined && map.set(seed, target = (i ? new Map() : factory(env)))
277
+
278
+ map = target;
226
279
  }
227
- });
228
280
 
281
+ return target;
282
+ };
283
+
284
+ const adapter = getFetch();
229
285
 
286
+ export default adapter;
@@ -25,6 +25,7 @@ import readBlob from "../helpers/readBlob.js";
25
25
  import ZlibHeaderTransformStream from '../helpers/ZlibHeaderTransformStream.js';
26
26
  import callbackify from "../helpers/callbackify.js";
27
27
  import {progressEventReducer, progressEventDecorator, asyncDecorator} from "../helpers/progressEventReducer.js";
28
+ import estimateDataURLDecodedBytes from '../helpers/estimateDataURLDecodedBytes.js';
28
29
 
29
30
  const zlibOptions = {
30
31
  flush: zlib.constants.Z_SYNC_FLUSH,
@@ -46,6 +47,7 @@ const supportedProtocols = platform.protocols.map(protocol => {
46
47
  return protocol + ':';
47
48
  });
48
49
 
50
+
49
51
  const flushOnFinish = (stream, [throttled, flush]) => {
50
52
  stream
51
53
  .on('end', flush)
@@ -54,6 +56,7 @@ const flushOnFinish = (stream, [throttled, flush]) => {
54
56
  return throttled;
55
57
  }
56
58
 
59
+
57
60
  /**
58
61
  * If the proxy or config beforeRedirects functions are defined, call them with the options
59
62
  * object.
@@ -228,11 +231,26 @@ export default isHttpAdapterSupported && function httpAdapter(config) {
228
231
  }
229
232
 
230
233
  // Parse url
231
- const fullPath = buildFullPath(config.baseURL, config.url);
234
+ const fullPath = buildFullPath(config.baseURL, config.url, config.allowAbsoluteUrls);
232
235
  const parsed = new URL(fullPath, platform.hasBrowserEnv ? platform.origin : undefined);
233
236
  const protocol = parsed.protocol || supportedProtocols[0];
234
237
 
235
238
  if (protocol === 'data:') {
239
+ // Apply the same semantics as HTTP: only enforce if a finite, non-negative cap is set.
240
+ if (config.maxContentLength > -1) {
241
+ // Use the exact string passed to fromDataURI (config.url); fall back to fullPath if needed.
242
+ const dataUrl = String(config.url || fullPath || '');
243
+ const estimated = estimateDataURLDecodedBytes(dataUrl);
244
+
245
+ if (estimated > config.maxContentLength) {
246
+ return reject(new AxiosError(
247
+ 'maxContentLength size of ' + config.maxContentLength + ' exceeded',
248
+ AxiosError.ERR_BAD_RESPONSE,
249
+ config
250
+ ));
251
+ }
252
+ }
253
+
236
254
  let convertedData;
237
255
 
238
256
  if (method !== 'GET') {
@@ -104,15 +104,18 @@ export default isXHRAdapterSupported && function (config) {
104
104
  };
105
105
 
106
106
  // Handle low level network errors
107
- request.onerror = function handleError() {
108
- // Real errors are hidden from us by the browser
109
- // onerror should only fire if it's a network error
110
- reject(new AxiosError('Network Error', AxiosError.ERR_NETWORK, config, request));
111
-
112
- // Clean up request
113
- request = null;
107
+ request.onerror = function handleError(event) {
108
+ // Browsers deliver a ProgressEvent in XHR onerror
109
+ // (message may be empty; when present, surface it)
110
+ // See https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/error_event
111
+ const msg = event && event.message ? event.message : 'Network Error';
112
+ const err = new AxiosError(msg, AxiosError.ERR_NETWORK, config, request);
113
+ // attach the underlying event for consumers who want details
114
+ err.event = event || null;
115
+ reject(err);
116
+ request = null;
114
117
  };
115
-
118
+
116
119
  // Handle timeout
117
120
  request.ontimeout = function handleTimeout() {
118
121
  let timeoutErrorMessage = _config.timeout ? 'timeout of ' + _config.timeout + 'ms exceeded' : 'timeout exceeded';
package/lib/core/Axios.js CHANGED
@@ -20,7 +20,7 @@ const validators = validator.validators;
20
20
  */
21
21
  class Axios {
22
22
  constructor(instanceConfig) {
23
- this.defaults = instanceConfig;
23
+ this.defaults = instanceConfig || {};
24
24
  this.interceptors = {
25
25
  request: new InterceptorManager(),
26
26
  response: new InterceptorManager()
@@ -97,6 +97,15 @@ class Axios {
97
97
  }
98
98
  }
99
99
 
100
+ // Set config.allowAbsoluteUrls
101
+ if (config.allowAbsoluteUrls !== undefined) {
102
+ // do nothing
103
+ } else if (this.defaults.allowAbsoluteUrls !== undefined) {
104
+ config.allowAbsoluteUrls = this.defaults.allowAbsoluteUrls;
105
+ } else {
106
+ config.allowAbsoluteUrls = true;
107
+ }
108
+
100
109
  validator.assertOptions(config, {
101
110
  baseUrl: validators.spelling('baseURL'),
102
111
  withXsrfToken: validators.spelling('withXSRFToken')
@@ -144,8 +153,8 @@ class Axios {
144
153
 
145
154
  if (!synchronousRequestInterceptors) {
146
155
  const chain = [dispatchRequest.bind(this), undefined];
147
- chain.unshift.apply(chain, requestInterceptorChain);
148
- chain.push.apply(chain, responseInterceptorChain);
156
+ chain.unshift(...requestInterceptorChain);
157
+ chain.push(...responseInterceptorChain);
149
158
  len = chain.length;
150
159
 
151
160
  promise = Promise.resolve(config);
@@ -192,7 +201,7 @@ class Axios {
192
201
 
193
202
  getUri(config) {
194
203
  config = mergeConfig(this.defaults, config);
195
- const fullPath = buildFullPath(config.baseURL, config.url);
204
+ const fullPath = buildFullPath(config.baseURL, config.url, config.allowAbsoluteUrls);
196
205
  return buildURL(fullPath, config.params, config.paramsSerializer);
197
206
  }
198
207
  }
@@ -89,11 +89,18 @@ AxiosError.from = (error, code, config, request, response, customProps) => {
89
89
  return prop !== 'isAxiosError';
90
90
  });
91
91
 
92
- AxiosError.call(axiosError, error.message, code, config, request, response);
92
+ const msg = error && error.message ? error.message : 'Error';
93
93
 
94
- axiosError.cause = error;
94
+ // Prefer explicit code; otherwise copy the low-level error's code (e.g. ECONNREFUSED)
95
+ const errCode = code == null && error ? error.code : code;
96
+ AxiosError.call(axiosError, msg, errCode, config, request, response);
95
97
 
96
- axiosError.name = error.name;
98
+ // Chain the original error on the standard field; non-enumerable to avoid JSON noise
99
+ if (error && axiosError.cause == null) {
100
+ Object.defineProperty(axiosError, 'cause', { value: error, configurable: true });
101
+ }
102
+
103
+ axiosError.name = (error && error.name) || 'Error';
97
104
 
98
105
  customProps && Object.assign(axiosError, customProps);
99
106
 
@@ -100,10 +100,18 @@ class AxiosHeaders {
100
100
  setHeaders(header, valueOrRewrite)
101
101
  } else if(utils.isString(header) && (header = header.trim()) && !isValidHeaderName(header)) {
102
102
  setHeaders(parseHeaders(header), valueOrRewrite);
103
- } else if (utils.isHeaders(header)) {
104
- for (const [key, value] of header.entries()) {
105
- setHeader(value, key, rewrite);
103
+ } else if (utils.isObject(header) && utils.isIterable(header)) {
104
+ let obj = {}, dest, key;
105
+ for (const entry of header) {
106
+ if (!utils.isArray(entry)) {
107
+ throw TypeError('Object iterator must return a key-value pair');
108
+ }
109
+
110
+ obj[key = entry[0]] = (dest = obj[key]) ?
111
+ (utils.isArray(dest) ? [...dest, entry[1]] : [dest, entry[1]]) : entry[1];
106
112
  }
113
+
114
+ setHeaders(obj, valueOrRewrite)
107
115
  } else {
108
116
  header != null && setHeader(valueOrRewrite, header, rewrite);
109
117
  }
@@ -245,6 +253,10 @@ class AxiosHeaders {
245
253
  return Object.entries(this.toJSON()).map(([header, value]) => header + ': ' + value).join('\n');
246
254
  }
247
255
 
256
+ getSetCookie() {
257
+ return this.get("set-cookie") || [];
258
+ }
259
+
248
260
  get [Symbol.toStringTag]() {
249
261
  return 'AxiosHeaders';
250
262
  }
@@ -13,8 +13,9 @@ import combineURLs from '../helpers/combineURLs.js';
13
13
  *
14
14
  * @returns {string} The combined full path
15
15
  */
16
- export default function buildFullPath(baseURL, requestedURL) {
17
- if (baseURL && !isAbsoluteURL(requestedURL)) {
16
+ export default function buildFullPath(baseURL, requestedURL, allowAbsoluteUrls) {
17
+ let isRelativeUrl = !isAbsoluteURL(requestedURL);
18
+ if (baseURL && (isRelativeUrl || allowAbsoluteUrls == false)) {
18
19
  return combineURLs(baseURL, requestedURL);
19
20
  }
20
21
  return requestedURL;
@@ -46,7 +46,7 @@ export default function dispatchRequest(config) {
46
46
  config.headers.setContentType('application/x-www-form-urlencoded', false);
47
47
  }
48
48
 
49
- const adapter = adapters.getAdapter(config.adapter || defaults.adapter);
49
+ const adapter = adapters.getAdapter(config.adapter || defaults.adapter, config);
50
50
 
51
51
  return adapter(config).then(function onAdapterResolution(response) {
52
52
  throwIfCancellationRequested(config);
@@ -96,7 +96,7 @@ export default function mergeConfig(config1, config2) {
96
96
  headers: (a, b , prop) => mergeDeepProperties(headersToObject(a), headersToObject(b),prop, true)
97
97
  };
98
98
 
99
- utils.forEach(Object.keys(Object.assign({}, config1, config2)), function computeConfigValue(prop) {
99
+ utils.forEach(Object.keys({...config1, ...config2}), function computeConfigValue(prop) {
100
100
  const merge = mergeMap[prop] || mergeDeepProperties;
101
101
  const configValue = merge(config1[prop], config2[prop], prop);
102
102
  (utils.isUndefined(configValue) && merge !== mergeDirectKeys) || (config[prop] = configValue);
@@ -111,7 +111,7 @@ const defaults = {
111
111
  const strictJSONParsing = !silentJSONParsing && JSONRequested;
112
112
 
113
113
  try {
114
- return JSON.parse(data);
114
+ return JSON.parse(data, this.parseReviver);
115
115
  } catch (e) {
116
116
  if (strictJSONParsing) {
117
117
  if (e.name === 'SyntaxError') {