| import utils from '../utils.js'; |
| import settle from '../core/settle.js'; |
| import buildFullPath from '../core/buildFullPath.js'; |
| import buildURL from '../helpers/buildURL.js'; |
| import { getProxyForUrl } from 'proxy-from-env'; |
| import http from 'http'; |
| import https from 'https'; |
| import http2 from 'http2'; |
| import util from 'util'; |
| import followRedirects from 'follow-redirects'; |
| import zlib from 'zlib'; |
| import { VERSION } from '../env/data.js'; |
| import transitionalDefaults from '../defaults/transitional.js'; |
| import AxiosError from '../core/AxiosError.js'; |
| import CanceledError from '../cancel/CanceledError.js'; |
| import platform from '../platform/index.js'; |
| import fromDataURI from '../helpers/fromDataURI.js'; |
| import stream from 'stream'; |
| import AxiosHeaders from '../core/AxiosHeaders.js'; |
| import AxiosTransformStream from '../helpers/AxiosTransformStream.js'; |
| import { EventEmitter } from 'events'; |
| import formDataToStream from '../helpers/formDataToStream.js'; |
| import readBlob from '../helpers/readBlob.js'; |
| import ZlibHeaderTransformStream from '../helpers/ZlibHeaderTransformStream.js'; |
| import callbackify from '../helpers/callbackify.js'; |
| import shouldBypassProxy from '../helpers/shouldBypassProxy.js'; |
| import { |
| progressEventReducer, |
| progressEventDecorator, |
| asyncDecorator, |
| } from '../helpers/progressEventReducer.js'; |
| import estimateDataURLDecodedBytes from '../helpers/estimateDataURLDecodedBytes.js'; |
|
|
| const zlibOptions = { |
| flush: zlib.constants.Z_SYNC_FLUSH, |
| finishFlush: zlib.constants.Z_SYNC_FLUSH, |
| }; |
|
|
| const brotliOptions = { |
| flush: zlib.constants.BROTLI_OPERATION_FLUSH, |
| finishFlush: zlib.constants.BROTLI_OPERATION_FLUSH, |
| }; |
|
|
| const isBrotliSupported = utils.isFunction(zlib.createBrotliDecompress); |
|
|
| const { http: httpFollow, https: httpsFollow } = followRedirects; |
|
|
| const isHttps = /https:?/; |
|
|
| const supportedProtocols = platform.protocols.map((protocol) => { |
| return protocol + ':'; |
| }); |
|
|
| const flushOnFinish = (stream, [throttled, flush]) => { |
| stream.on('end', flush).on('error', flush); |
|
|
| return throttled; |
| }; |
|
|
| class Http2Sessions { |
| constructor() { |
| this.sessions = Object.create(null); |
| } |
|
|
| getSession(authority, options) { |
| options = Object.assign( |
| { |
| sessionTimeout: 1000, |
| }, |
| options |
| ); |
|
|
| let authoritySessions = this.sessions[authority]; |
|
|
| if (authoritySessions) { |
| let len = authoritySessions.length; |
|
|
| for (let i = 0; i < len; i++) { |
| const [sessionHandle, sessionOptions] = authoritySessions[i]; |
| if ( |
| !sessionHandle.destroyed && |
| !sessionHandle.closed && |
| util.isDeepStrictEqual(sessionOptions, options) |
| ) { |
| return sessionHandle; |
| } |
| } |
| } |
|
|
| const session = http2.connect(authority, options); |
|
|
| let removed; |
|
|
| const removeSession = () => { |
| if (removed) { |
| return; |
| } |
|
|
| removed = true; |
|
|
| let entries = authoritySessions, |
| len = entries.length, |
| i = len; |
|
|
| while (i--) { |
| if (entries[i][0] === session) { |
| if (len === 1) { |
| delete this.sessions[authority]; |
| } else { |
| entries.splice(i, 1); |
| } |
| if (!session.closed) { |
| session.close(); |
| } |
| return; |
| } |
| } |
| }; |
|
|
| const originalRequestFn = session.request; |
|
|
| const { sessionTimeout } = options; |
|
|
| if (sessionTimeout != null) { |
| let timer; |
| let streamsCount = 0; |
|
|
| session.request = function () { |
| const stream = originalRequestFn.apply(this, arguments); |
|
|
| streamsCount++; |
|
|
| if (timer) { |
| clearTimeout(timer); |
| timer = null; |
| } |
|
|
| stream.once('close', () => { |
| if (!--streamsCount) { |
| timer = setTimeout(() => { |
| timer = null; |
| removeSession(); |
| }, sessionTimeout); |
| } |
| }); |
|
|
| return stream; |
| }; |
| } |
|
|
| session.once('close', removeSession); |
|
|
| let entry = [session, options]; |
|
|
| authoritySessions |
| ? authoritySessions.push(entry) |
| : (authoritySessions = this.sessions[authority] = [entry]); |
|
|
| return session; |
| } |
| } |
|
|
| const http2Sessions = new Http2Sessions(); |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| function dispatchBeforeRedirect(options, responseDetails) { |
| if (options.beforeRedirects.proxy) { |
| options.beforeRedirects.proxy(options); |
| } |
| if (options.beforeRedirects.config) { |
| options.beforeRedirects.config(options, responseDetails); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| function setProxy(options, configProxy, location) { |
| let proxy = configProxy; |
| if (!proxy && proxy !== false) { |
| const proxyUrl = getProxyForUrl(location); |
| if (proxyUrl) { |
| if (!shouldBypassProxy(location)) { |
| proxy = new URL(proxyUrl); |
| } |
| } |
| } |
| if (proxy) { |
| |
| if (proxy.username) { |
| proxy.auth = (proxy.username || '') + ':' + (proxy.password || ''); |
| } |
|
|
| if (proxy.auth) { |
| |
| const validProxyAuth = Boolean(proxy.auth.username || proxy.auth.password); |
|
|
| if (validProxyAuth) { |
| proxy.auth = (proxy.auth.username || '') + ':' + (proxy.auth.password || ''); |
| } else if (typeof proxy.auth === 'object') { |
| throw new AxiosError('Invalid proxy authorization', AxiosError.ERR_BAD_OPTION, { proxy }); |
| } |
|
|
| const base64 = Buffer.from(proxy.auth, 'utf8').toString('base64'); |
|
|
| options.headers['Proxy-Authorization'] = 'Basic ' + base64; |
| } |
|
|
| options.headers.host = options.hostname + (options.port ? ':' + options.port : ''); |
| const proxyHost = proxy.hostname || proxy.host; |
| options.hostname = proxyHost; |
| |
| options.host = proxyHost; |
| options.port = proxy.port; |
| options.path = location; |
| if (proxy.protocol) { |
| options.protocol = proxy.protocol.includes(':') ? proxy.protocol : `${proxy.protocol}:`; |
| } |
| } |
|
|
| options.beforeRedirects.proxy = function beforeRedirect(redirectOptions) { |
| |
| |
| setProxy(redirectOptions, configProxy, redirectOptions.href); |
| }; |
| } |
|
|
| const isHttpAdapterSupported = |
| typeof process !== 'undefined' && utils.kindOf(process) === 'process'; |
|
|
| |
|
|
| const wrapAsync = (asyncExecutor) => { |
| return new Promise((resolve, reject) => { |
| let onDone; |
| let isDone; |
|
|
| const done = (value, isRejected) => { |
| if (isDone) return; |
| isDone = true; |
| onDone && onDone(value, isRejected); |
| }; |
|
|
| const _resolve = (value) => { |
| done(value); |
| resolve(value); |
| }; |
|
|
| const _reject = (reason) => { |
| done(reason, true); |
| reject(reason); |
| }; |
|
|
| asyncExecutor(_resolve, _reject, (onDoneHandler) => (onDone = onDoneHandler)).catch(_reject); |
| }); |
| }; |
|
|
| const resolveFamily = ({ address, family }) => { |
| if (!utils.isString(address)) { |
| throw TypeError('address must be a string'); |
| } |
| return { |
| address, |
| family: family || (address.indexOf('.') < 0 ? 6 : 4), |
| }; |
| }; |
|
|
| const buildAddressEntry = (address, family) => |
| resolveFamily(utils.isObject(address) ? address : { address, family }); |
|
|
| const http2Transport = { |
| request(options, cb) { |
| const authority = |
| options.protocol + |
| '//' + |
| options.hostname + |
| ':' + |
| (options.port || (options.protocol === 'https:' ? 443 : 80)); |
|
|
| const { http2Options, headers } = options; |
|
|
| const session = http2Sessions.getSession(authority, http2Options); |
|
|
| const { HTTP2_HEADER_SCHEME, HTTP2_HEADER_METHOD, HTTP2_HEADER_PATH, HTTP2_HEADER_STATUS } = |
| http2.constants; |
|
|
| const http2Headers = { |
| [HTTP2_HEADER_SCHEME]: options.protocol.replace(':', ''), |
| [HTTP2_HEADER_METHOD]: options.method, |
| [HTTP2_HEADER_PATH]: options.path, |
| }; |
|
|
| utils.forEach(headers, (header, name) => { |
| name.charAt(0) !== ':' && (http2Headers[name] = header); |
| }); |
|
|
| const req = session.request(http2Headers); |
|
|
| req.once('response', (responseHeaders) => { |
| const response = req; |
|
|
| responseHeaders = Object.assign({}, responseHeaders); |
|
|
| const status = responseHeaders[HTTP2_HEADER_STATUS]; |
|
|
| delete responseHeaders[HTTP2_HEADER_STATUS]; |
|
|
| response.headers = responseHeaders; |
|
|
| response.statusCode = +status; |
|
|
| cb(response); |
| }); |
|
|
| return req; |
| }, |
| }; |
|
|
| |
| export default isHttpAdapterSupported && |
| function httpAdapter(config) { |
| return wrapAsync(async function dispatchHttpRequest(resolve, reject, onDone) { |
| let { data, lookup, family, httpVersion = 1, http2Options } = config; |
| const { responseType, responseEncoding } = config; |
| const method = config.method.toUpperCase(); |
| let isDone; |
| let rejected = false; |
| let req; |
|
|
| httpVersion = +httpVersion; |
|
|
| if (Number.isNaN(httpVersion)) { |
| throw TypeError(`Invalid protocol version: '${config.httpVersion}' is not a number`); |
| } |
|
|
| if (httpVersion !== 1 && httpVersion !== 2) { |
| throw TypeError(`Unsupported protocol version '${httpVersion}'`); |
| } |
|
|
| const isHttp2 = httpVersion === 2; |
|
|
| if (lookup) { |
| const _lookup = callbackify(lookup, (value) => (utils.isArray(value) ? value : [value])); |
| |
| lookup = (hostname, opt, cb) => { |
| _lookup(hostname, opt, (err, arg0, arg1) => { |
| if (err) { |
| return cb(err); |
| } |
|
|
| const addresses = utils.isArray(arg0) |
| ? arg0.map((addr) => buildAddressEntry(addr)) |
| : [buildAddressEntry(arg0, arg1)]; |
|
|
| opt.all ? cb(err, addresses) : cb(err, addresses[0].address, addresses[0].family); |
| }); |
| }; |
| } |
|
|
| const abortEmitter = new EventEmitter(); |
|
|
| function abort(reason) { |
| try { |
| abortEmitter.emit( |
| 'abort', |
| !reason || reason.type ? new CanceledError(null, config, req) : reason |
| ); |
| } catch (err) { |
| console.warn('emit error', err); |
| } |
| } |
|
|
| abortEmitter.once('abort', reject); |
|
|
| const onFinished = () => { |
| if (config.cancelToken) { |
| config.cancelToken.unsubscribe(abort); |
| } |
|
|
| if (config.signal) { |
| config.signal.removeEventListener('abort', abort); |
| } |
|
|
| abortEmitter.removeAllListeners(); |
| }; |
|
|
| if (config.cancelToken || config.signal) { |
| config.cancelToken && config.cancelToken.subscribe(abort); |
| if (config.signal) { |
| config.signal.aborted ? abort() : config.signal.addEventListener('abort', abort); |
| } |
| } |
|
|
| onDone((response, isRejected) => { |
| isDone = true; |
|
|
| if (isRejected) { |
| rejected = true; |
| onFinished(); |
| return; |
| } |
|
|
| const { data } = response; |
|
|
| if (data instanceof stream.Readable || data instanceof stream.Duplex) { |
| const offListeners = stream.finished(data, () => { |
| offListeners(); |
| onFinished(); |
| }); |
| } else { |
| onFinished(); |
| } |
| }); |
|
|
| |
| const fullPath = buildFullPath(config.baseURL, config.url, config.allowAbsoluteUrls); |
| const parsed = new URL(fullPath, platform.hasBrowserEnv ? platform.origin : undefined); |
| const protocol = parsed.protocol || supportedProtocols[0]; |
|
|
| if (protocol === 'data:') { |
| |
| if (config.maxContentLength > -1) { |
| |
| const dataUrl = String(config.url || fullPath || ''); |
| const estimated = estimateDataURLDecodedBytes(dataUrl); |
|
|
| if (estimated > config.maxContentLength) { |
| return reject( |
| new AxiosError( |
| 'maxContentLength size of ' + config.maxContentLength + ' exceeded', |
| AxiosError.ERR_BAD_RESPONSE, |
| config |
| ) |
| ); |
| } |
| } |
|
|
| let convertedData; |
|
|
| if (method !== 'GET') { |
| return settle(resolve, reject, { |
| status: 405, |
| statusText: 'method not allowed', |
| headers: {}, |
| config, |
| }); |
| } |
|
|
| try { |
| convertedData = fromDataURI(config.url, responseType === 'blob', { |
| Blob: config.env && config.env.Blob, |
| }); |
| } catch (err) { |
| throw AxiosError.from(err, AxiosError.ERR_BAD_REQUEST, config); |
| } |
|
|
| if (responseType === 'text') { |
| convertedData = convertedData.toString(responseEncoding); |
|
|
| if (!responseEncoding || responseEncoding === 'utf8') { |
| convertedData = utils.stripBOM(convertedData); |
| } |
| } else if (responseType === 'stream') { |
| convertedData = stream.Readable.from(convertedData); |
| } |
|
|
| return settle(resolve, reject, { |
| data: convertedData, |
| status: 200, |
| statusText: 'OK', |
| headers: new AxiosHeaders(), |
| config, |
| }); |
| } |
|
|
| if (supportedProtocols.indexOf(protocol) === -1) { |
| return reject( |
| new AxiosError('Unsupported protocol ' + protocol, AxiosError.ERR_BAD_REQUEST, config) |
| ); |
| } |
|
|
| const headers = AxiosHeaders.from(config.headers).normalize(); |
|
|
| |
| |
| |
| |
| headers.set('User-Agent', 'axios/' + VERSION, false); |
|
|
| const { onUploadProgress, onDownloadProgress } = config; |
| const maxRate = config.maxRate; |
| let maxUploadRate = undefined; |
| let maxDownloadRate = undefined; |
|
|
| |
| if (utils.isSpecCompliantForm(data)) { |
| const userBoundary = headers.getContentType(/boundary=([-_\w\d]{10,70})/i); |
|
|
| data = formDataToStream( |
| data, |
| (formHeaders) => { |
| headers.set(formHeaders); |
| }, |
| { |
| tag: `axios-${VERSION}-boundary`, |
| boundary: (userBoundary && userBoundary[1]) || undefined, |
| } |
| ); |
| |
| } else if (utils.isFormData(data) && utils.isFunction(data.getHeaders)) { |
| headers.set(data.getHeaders()); |
|
|
| if (!headers.hasContentLength()) { |
| try { |
| const knownLength = await util.promisify(data.getLength).call(data); |
| Number.isFinite(knownLength) && |
| knownLength >= 0 && |
| headers.setContentLength(knownLength); |
| |
| } catch (e) {} |
| } |
| } else if (utils.isBlob(data) || utils.isFile(data)) { |
| data.size && headers.setContentType(data.type || 'application/octet-stream'); |
| headers.setContentLength(data.size || 0); |
| data = stream.Readable.from(readBlob(data)); |
| } else if (data && !utils.isStream(data)) { |
| if (Buffer.isBuffer(data)) { |
| |
| } else if (utils.isArrayBuffer(data)) { |
| data = Buffer.from(new Uint8Array(data)); |
| } else if (utils.isString(data)) { |
| data = Buffer.from(data, 'utf-8'); |
| } else { |
| return reject( |
| new AxiosError( |
| 'Data after transformation must be a string, an ArrayBuffer, a Buffer, or a Stream', |
| AxiosError.ERR_BAD_REQUEST, |
| config |
| ) |
| ); |
| } |
|
|
| |
| headers.setContentLength(data.length, false); |
|
|
| if (config.maxBodyLength > -1 && data.length > config.maxBodyLength) { |
| return reject( |
| new AxiosError( |
| 'Request body larger than maxBodyLength limit', |
| AxiosError.ERR_BAD_REQUEST, |
| config |
| ) |
| ); |
| } |
| } |
|
|
| const contentLength = utils.toFiniteNumber(headers.getContentLength()); |
|
|
| if (utils.isArray(maxRate)) { |
| maxUploadRate = maxRate[0]; |
| maxDownloadRate = maxRate[1]; |
| } else { |
| maxUploadRate = maxDownloadRate = maxRate; |
| } |
|
|
| if (data && (onUploadProgress || maxUploadRate)) { |
| if (!utils.isStream(data)) { |
| data = stream.Readable.from(data, { objectMode: false }); |
| } |
|
|
| data = stream.pipeline( |
| [ |
| data, |
| new AxiosTransformStream({ |
| maxRate: utils.toFiniteNumber(maxUploadRate), |
| }), |
| ], |
| utils.noop |
| ); |
|
|
| onUploadProgress && |
| data.on( |
| 'progress', |
| flushOnFinish( |
| data, |
| progressEventDecorator( |
| contentLength, |
| progressEventReducer(asyncDecorator(onUploadProgress), false, 3) |
| ) |
| ) |
| ); |
| } |
|
|
| |
| let auth = undefined; |
| if (config.auth) { |
| const username = config.auth.username || ''; |
| const password = config.auth.password || ''; |
| auth = username + ':' + password; |
| } |
|
|
| if (!auth && parsed.username) { |
| const urlUsername = parsed.username; |
| const urlPassword = parsed.password; |
| auth = urlUsername + ':' + urlPassword; |
| } |
|
|
| auth && headers.delete('authorization'); |
|
|
| let path; |
|
|
| try { |
| path = buildURL( |
| parsed.pathname + parsed.search, |
| config.params, |
| config.paramsSerializer |
| ).replace(/^\?/, ''); |
| } catch (err) { |
| const customErr = new Error(err.message); |
| customErr.config = config; |
| customErr.url = config.url; |
| customErr.exists = true; |
| return reject(customErr); |
| } |
|
|
| headers.set( |
| 'Accept-Encoding', |
| 'gzip, compress, deflate' + (isBrotliSupported ? ', br' : ''), |
| false |
| ); |
|
|
| const options = { |
| path, |
| method: method, |
| headers: headers.toJSON(), |
| agents: { http: config.httpAgent, https: config.httpsAgent }, |
| auth, |
| protocol, |
| family, |
| beforeRedirect: dispatchBeforeRedirect, |
| beforeRedirects: {}, |
| http2Options, |
| }; |
|
|
| |
| !utils.isUndefined(lookup) && (options.lookup = lookup); |
|
|
| if (config.socketPath) { |
| options.socketPath = config.socketPath; |
| } else { |
| options.hostname = parsed.hostname.startsWith('[') |
| ? parsed.hostname.slice(1, -1) |
| : parsed.hostname; |
| options.port = parsed.port; |
| setProxy( |
| options, |
| config.proxy, |
| protocol + '//' + parsed.hostname + (parsed.port ? ':' + parsed.port : '') + options.path |
| ); |
| } |
| let transport; |
| const isHttpsRequest = isHttps.test(options.protocol); |
| options.agent = isHttpsRequest ? config.httpsAgent : config.httpAgent; |
|
|
| if (isHttp2) { |
| transport = http2Transport; |
| } else { |
| if (config.transport) { |
| transport = config.transport; |
| } else if (config.maxRedirects === 0) { |
| transport = isHttpsRequest ? https : http; |
| } else { |
| if (config.maxRedirects) { |
| options.maxRedirects = config.maxRedirects; |
| } |
| if (config.beforeRedirect) { |
| options.beforeRedirects.config = config.beforeRedirect; |
| } |
| transport = isHttpsRequest ? httpsFollow : httpFollow; |
| } |
| } |
|
|
| if (config.maxBodyLength > -1) { |
| options.maxBodyLength = config.maxBodyLength; |
| } else { |
| |
| options.maxBodyLength = Infinity; |
| } |
|
|
| if (config.insecureHTTPParser) { |
| options.insecureHTTPParser = config.insecureHTTPParser; |
| } |
|
|
| |
| req = transport.request(options, function handleResponse(res) { |
| if (req.destroyed) return; |
|
|
| const streams = [res]; |
|
|
| const responseLength = utils.toFiniteNumber(res.headers['content-length']); |
|
|
| if (onDownloadProgress || maxDownloadRate) { |
| const transformStream = new AxiosTransformStream({ |
| maxRate: utils.toFiniteNumber(maxDownloadRate), |
| }); |
|
|
| onDownloadProgress && |
| transformStream.on( |
| 'progress', |
| flushOnFinish( |
| transformStream, |
| progressEventDecorator( |
| responseLength, |
| progressEventReducer(asyncDecorator(onDownloadProgress), true, 3) |
| ) |
| ) |
| ); |
|
|
| streams.push(transformStream); |
| } |
|
|
| |
| let responseStream = res; |
|
|
| |
| const lastRequest = res.req || req; |
|
|
| |
| if (config.decompress !== false && res.headers['content-encoding']) { |
| |
| |
| if (method === 'HEAD' || res.statusCode === 204) { |
| delete res.headers['content-encoding']; |
| } |
|
|
| switch ((res.headers['content-encoding'] || '').toLowerCase()) { |
| |
| case 'gzip': |
| case 'x-gzip': |
| case 'compress': |
| case 'x-compress': |
| |
| streams.push(zlib.createUnzip(zlibOptions)); |
|
|
| |
| delete res.headers['content-encoding']; |
| break; |
| case 'deflate': |
| streams.push(new ZlibHeaderTransformStream()); |
|
|
| |
| streams.push(zlib.createUnzip(zlibOptions)); |
|
|
| |
| delete res.headers['content-encoding']; |
| break; |
| case 'br': |
| if (isBrotliSupported) { |
| streams.push(zlib.createBrotliDecompress(brotliOptions)); |
| delete res.headers['content-encoding']; |
| } |
| } |
| } |
|
|
| responseStream = streams.length > 1 ? stream.pipeline(streams, utils.noop) : streams[0]; |
|
|
| const response = { |
| status: res.statusCode, |
| statusText: res.statusMessage, |
| headers: new AxiosHeaders(res.headers), |
| config, |
| request: lastRequest, |
| }; |
|
|
| if (responseType === 'stream') { |
| response.data = responseStream; |
| settle(resolve, reject, response); |
| } else { |
| const responseBuffer = []; |
| let totalResponseBytes = 0; |
|
|
| responseStream.on('data', function handleStreamData(chunk) { |
| responseBuffer.push(chunk); |
| totalResponseBytes += chunk.length; |
|
|
| |
| if (config.maxContentLength > -1 && totalResponseBytes > config.maxContentLength) { |
| |
| rejected = true; |
| responseStream.destroy(); |
| abort( |
| new AxiosError( |
| 'maxContentLength size of ' + config.maxContentLength + ' exceeded', |
| AxiosError.ERR_BAD_RESPONSE, |
| config, |
| lastRequest |
| ) |
| ); |
| } |
| }); |
|
|
| responseStream.on('aborted', function handlerStreamAborted() { |
| if (rejected) { |
| return; |
| } |
|
|
| const err = new AxiosError( |
| 'stream has been aborted', |
| AxiosError.ERR_BAD_RESPONSE, |
| config, |
| lastRequest |
| ); |
| responseStream.destroy(err); |
| reject(err); |
| }); |
|
|
| responseStream.on('error', function handleStreamError(err) { |
| if (req.destroyed) return; |
| reject(AxiosError.from(err, null, config, lastRequest)); |
| }); |
|
|
| responseStream.on('end', function handleStreamEnd() { |
| try { |
| let responseData = |
| responseBuffer.length === 1 ? responseBuffer[0] : Buffer.concat(responseBuffer); |
| if (responseType !== 'arraybuffer') { |
| responseData = responseData.toString(responseEncoding); |
| if (!responseEncoding || responseEncoding === 'utf8') { |
| responseData = utils.stripBOM(responseData); |
| } |
| } |
| response.data = responseData; |
| } catch (err) { |
| return reject(AxiosError.from(err, null, config, response.request, response)); |
| } |
| settle(resolve, reject, response); |
| }); |
| } |
|
|
| abortEmitter.once('abort', (err) => { |
| if (!responseStream.destroyed) { |
| responseStream.emit('error', err); |
| responseStream.destroy(); |
| } |
| }); |
| }); |
|
|
| abortEmitter.once('abort', (err) => { |
| if (req.close) { |
| req.close(); |
| } else { |
| req.destroy(err); |
| } |
| }); |
|
|
| |
| req.on('error', function handleRequestError(err) { |
| reject(AxiosError.from(err, null, config, req)); |
| }); |
|
|
| |
| req.on('socket', function handleRequestSocket(socket) { |
| |
| socket.setKeepAlive(true, 1000 * 60); |
| }); |
|
|
| |
| if (config.timeout) { |
| |
| const timeout = parseInt(config.timeout, 10); |
|
|
| if (Number.isNaN(timeout)) { |
| abort( |
| new AxiosError( |
| 'error trying to parse `config.timeout` to int', |
| AxiosError.ERR_BAD_OPTION_VALUE, |
| config, |
| req |
| ) |
| ); |
|
|
| return; |
| } |
|
|
| |
| |
| |
| |
| |
| req.setTimeout(timeout, function handleRequestTimeout() { |
| if (isDone) return; |
| let timeoutErrorMessage = config.timeout |
| ? 'timeout of ' + config.timeout + 'ms exceeded' |
| : 'timeout exceeded'; |
| const transitional = config.transitional || transitionalDefaults; |
| if (config.timeoutErrorMessage) { |
| timeoutErrorMessage = config.timeoutErrorMessage; |
| } |
| abort( |
| new AxiosError( |
| timeoutErrorMessage, |
| transitional.clarifyTimeoutError ? AxiosError.ETIMEDOUT : AxiosError.ECONNABORTED, |
| config, |
| req |
| ) |
| ); |
| }); |
| } else { |
| |
| req.setTimeout(0); |
| } |
|
|
| |
| if (utils.isStream(data)) { |
| let ended = false; |
| let errored = false; |
|
|
| data.on('end', () => { |
| ended = true; |
| }); |
|
|
| data.once('error', (err) => { |
| errored = true; |
| req.destroy(err); |
| }); |
|
|
| data.on('close', () => { |
| if (!ended && !errored) { |
| abort(new CanceledError('Request stream has been aborted', config, req)); |
| } |
| }); |
|
|
| data.pipe(req); |
| } else { |
| data && req.write(data); |
| req.end(); |
| } |
| }); |
| }; |
|
|
| export const __setProxy = setProxy; |
|
|