| | 'use strict'; |
| |
|
| | import utils from './../utils.js'; |
| | import settle from './../core/settle.js'; |
| | import cookies from './../helpers/cookies.js'; |
| | import buildURL from './../helpers/buildURL.js'; |
| | import buildFullPath from '../core/buildFullPath.js'; |
| | import isURLSameOrigin from './../helpers/isURLSameOrigin.js'; |
| | import transitionalDefaults from '../defaults/transitional.js'; |
| | import AxiosError from '../core/AxiosError.js'; |
| | import CanceledError from '../cancel/CanceledError.js'; |
| | import parseProtocol from '../helpers/parseProtocol.js'; |
| | import platform from '../platform/index.js'; |
| | import AxiosHeaders from '../core/AxiosHeaders.js'; |
| | import speedometer from '../helpers/speedometer.js'; |
| |
|
| | function progressEventReducer(listener, isDownloadStream) { |
| | let bytesNotified = 0; |
| | const _speedometer = speedometer(50, 250); |
| |
|
| | return e => { |
| | const loaded = e.loaded; |
| | const total = e.lengthComputable ? e.total : undefined; |
| | const progressBytes = loaded - bytesNotified; |
| | const rate = _speedometer(progressBytes); |
| | const inRange = loaded <= total; |
| |
|
| | bytesNotified = loaded; |
| |
|
| | const data = { |
| | loaded, |
| | total, |
| | progress: total ? (loaded / total) : undefined, |
| | bytes: progressBytes, |
| | rate: rate ? rate : undefined, |
| | estimated: rate && total && inRange ? (total - loaded) / rate : undefined, |
| | event: e |
| | }; |
| |
|
| | data[isDownloadStream ? 'download' : 'upload'] = true; |
| |
|
| | listener(data); |
| | }; |
| | } |
| |
|
| | const isXHRAdapterSupported = typeof XMLHttpRequest !== 'undefined'; |
| |
|
| | export default isXHRAdapterSupported && function (config) { |
| | return new Promise(function dispatchXhrRequest(resolve, reject) { |
| | let requestData = config.data; |
| | const requestHeaders = AxiosHeaders.from(config.headers).normalize(); |
| | let {responseType, withXSRFToken} = config; |
| | let onCanceled; |
| | function done() { |
| | if (config.cancelToken) { |
| | config.cancelToken.unsubscribe(onCanceled); |
| | } |
| |
|
| | if (config.signal) { |
| | config.signal.removeEventListener('abort', onCanceled); |
| | } |
| | } |
| |
|
| | let contentType; |
| |
|
| | if (utils.isFormData(requestData)) { |
| | if (platform.hasStandardBrowserEnv || platform.hasStandardBrowserWebWorkerEnv) { |
| | requestHeaders.setContentType(false); |
| | } else if ((contentType = requestHeaders.getContentType()) !== false) { |
| | |
| | const [type, ...tokens] = contentType ? contentType.split(';').map(token => token.trim()).filter(Boolean) : []; |
| | requestHeaders.setContentType([type || 'multipart/form-data', ...tokens].join('; ')); |
| | } |
| | } |
| |
|
| | let request = new XMLHttpRequest(); |
| |
|
| | |
| | if (config.auth) { |
| | const username = config.auth.username || ''; |
| | const password = config.auth.password ? unescape(encodeURIComponent(config.auth.password)) : ''; |
| | requestHeaders.set('Authorization', 'Basic ' + btoa(username + ':' + password)); |
| | } |
| |
|
| | const fullPath = buildFullPath(config.baseURL, config.url); |
| |
|
| | request.open(config.method.toUpperCase(), buildURL(fullPath, config.params, config.paramsSerializer), true); |
| |
|
| | |
| | request.timeout = config.timeout; |
| |
|
| | function onloadend() { |
| | if (!request) { |
| | return; |
| | } |
| | |
| | const responseHeaders = AxiosHeaders.from( |
| | 'getAllResponseHeaders' in request && request.getAllResponseHeaders() |
| | ); |
| | const responseData = !responseType || responseType === 'text' || responseType === 'json' ? |
| | request.responseText : request.response; |
| | const response = { |
| | data: responseData, |
| | status: request.status, |
| | statusText: request.statusText, |
| | headers: responseHeaders, |
| | config, |
| | request |
| | }; |
| |
|
| | settle(function _resolve(value) { |
| | resolve(value); |
| | done(); |
| | }, function _reject(err) { |
| | reject(err); |
| | done(); |
| | }, response); |
| |
|
| | |
| | request = null; |
| | } |
| |
|
| | if ('onloadend' in request) { |
| | |
| | request.onloadend = onloadend; |
| | } else { |
| | |
| | request.onreadystatechange = function handleLoad() { |
| | if (!request || request.readyState !== 4) { |
| | return; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) { |
| | return; |
| | } |
| | |
| | |
| | setTimeout(onloadend); |
| | }; |
| | } |
| |
|
| | |
| | request.onabort = function handleAbort() { |
| | if (!request) { |
| | return; |
| | } |
| |
|
| | reject(new AxiosError('Request aborted', AxiosError.ECONNABORTED, config, request)); |
| |
|
| | |
| | request = null; |
| | }; |
| |
|
| | |
| | request.onerror = function handleError() { |
| | |
| | |
| | reject(new AxiosError('Network Error', AxiosError.ERR_NETWORK, config, request)); |
| |
|
| | |
| | request = null; |
| | }; |
| |
|
| | |
| | request.ontimeout = function handleTimeout() { |
| | let timeoutErrorMessage = config.timeout ? 'timeout of ' + config.timeout + 'ms exceeded' : 'timeout exceeded'; |
| | const transitional = config.transitional || transitionalDefaults; |
| | if (config.timeoutErrorMessage) { |
| | timeoutErrorMessage = config.timeoutErrorMessage; |
| | } |
| | reject(new AxiosError( |
| | timeoutErrorMessage, |
| | transitional.clarifyTimeoutError ? AxiosError.ETIMEDOUT : AxiosError.ECONNABORTED, |
| | config, |
| | request)); |
| |
|
| | |
| | request = null; |
| | }; |
| |
|
| | |
| | |
| | |
| | if(platform.hasStandardBrowserEnv) { |
| | withXSRFToken && utils.isFunction(withXSRFToken) && (withXSRFToken = withXSRFToken(config)); |
| |
|
| | if (withXSRFToken || (withXSRFToken !== false && isURLSameOrigin(fullPath))) { |
| | |
| | const xsrfValue = config.xsrfHeaderName && config.xsrfCookieName && cookies.read(config.xsrfCookieName); |
| |
|
| | if (xsrfValue) { |
| | requestHeaders.set(config.xsrfHeaderName, xsrfValue); |
| | } |
| | } |
| | } |
| |
|
| | |
| | requestData === undefined && requestHeaders.setContentType(null); |
| |
|
| | |
| | if ('setRequestHeader' in request) { |
| | utils.forEach(requestHeaders.toJSON(), function setRequestHeader(val, key) { |
| | request.setRequestHeader(key, val); |
| | }); |
| | } |
| |
|
| | |
| | if (!utils.isUndefined(config.withCredentials)) { |
| | request.withCredentials = !!config.withCredentials; |
| | } |
| |
|
| | |
| | if (responseType && responseType !== 'json') { |
| | request.responseType = config.responseType; |
| | } |
| |
|
| | |
| | if (typeof config.onDownloadProgress === 'function') { |
| | request.addEventListener('progress', progressEventReducer(config.onDownloadProgress, true)); |
| | } |
| |
|
| | |
| | if (typeof config.onUploadProgress === 'function' && request.upload) { |
| | request.upload.addEventListener('progress', progressEventReducer(config.onUploadProgress)); |
| | } |
| |
|
| | if (config.cancelToken || config.signal) { |
| | |
| | |
| | onCanceled = cancel => { |
| | if (!request) { |
| | return; |
| | } |
| | reject(!cancel || cancel.type ? new CanceledError(null, config, request) : cancel); |
| | request.abort(); |
| | request = null; |
| | }; |
| |
|
| | config.cancelToken && config.cancelToken.subscribe(onCanceled); |
| | if (config.signal) { |
| | config.signal.aborted ? onCanceled() : config.signal.addEventListener('abort', onCanceled); |
| | } |
| | } |
| |
|
| | const protocol = parseProtocol(fullPath); |
| |
|
| | if (protocol && platform.protocols.indexOf(protocol) === -1) { |
| | reject(new AxiosError('Unsupported protocol ' + protocol + ':', AxiosError.ERR_BAD_REQUEST, config)); |
| | return; |
| | } |
| |
|
| |
|
| | |
| | request.send(requestData || null); |
| | }); |
| | } |
| |
|