opusdev/vector-similarity-api
1
1import utils from '../utils.js';2import settle from '../core/settle.js';3import buildFullPath from '../core/buildFullPath.js';4import buildURL from '../helpers/buildURL.js';5import proxyFromEnv from 'proxy-from-env';6import http from 'http';7import https from 'https';8import http2 from 'http2';9import util from 'util';10import followRedirects from 'follow-redirects';11import zlib from 'zlib';12import {VERSION} from '../env/data.js';13import transitionalDefaults from '../defaults/transitional.js';14import AxiosError from '../core/AxiosError.js';15import CanceledError from '../cancel/CanceledError.js';16import platform from '../platform/index.js';17import fromDataURI from '../helpers/fromDataURI.js';18import stream from 'stream';19import AxiosHeaders from '../core/AxiosHeaders.js';20import AxiosTransformStream from '../helpers/AxiosTransformStream.js';21import {EventEmitter} from 'events';22import formDataToStream from "../helpers/formDataToStream.js";23import readBlob from "../helpers/readBlob.js";24import ZlibHeaderTransformStream from '../helpers/ZlibHeaderTransformStream.js';25import callbackify from "../helpers/callbackify.js";26import {progressEventReducer, progressEventDecorator, asyncDecorator} from "../helpers/progressEventReducer.js";27import estimateDataURLDecodedBytes from '../helpers/estimateDataURLDecodedBytes.js';28 29const zlibOptions = {30 flush: zlib.constants.Z_SYNC_FLUSH,31 finishFlush: zlib.constants.Z_SYNC_FLUSH32};33 34const brotliOptions = {35 flush: zlib.constants.BROTLI_OPERATION_FLUSH,36 finishFlush: zlib.constants.BROTLI_OPERATION_FLUSH37}38 39const isBrotliSupported = utils.isFunction(zlib.createBrotliDecompress);40 41const {http: httpFollow, https: httpsFollow} = followRedirects;42 43const isHttps = /https:?/;44 45const supportedProtocols = platform.protocols.map(protocol => {46 return protocol + ':';47});48 49 50const flushOnFinish = (stream, [throttled, flush]) => {51 stream52 .on('end', flush)53 .on('error', flush);54 55 return throttled;56}57 58class Http2Sessions {59 constructor() {60 this.sessions = Object.create(null);61 }62 63 getSession(authority, options) {64 options = Object.assign({65 sessionTimeout: 100066 }, options);67 68 let authoritySessions = this.sessions[authority];69 70 if (authoritySessions) {71 let len = authoritySessions.length;72 73 for (let i = 0; i < len; i++) {74 const [sessionHandle, sessionOptions] = authoritySessions[i];75 if (!sessionHandle.destroyed && !sessionHandle.closed && util.isDeepStrictEqual(sessionOptions, options)) {76 return sessionHandle;77 }78 }79 }80 81 const session = http2.connect(authority, options);82 83 let removed;84 85 const removeSession = () => {86 if (removed) {87 return;88 }89 90 removed = true;91 92 let entries = authoritySessions, len = entries.length, i = len;93 94 while (i--) {95 if (entries[i][0] === session) {96 if (len === 1) {97 delete this.sessions[authority];98 } else {99 entries.splice(i, 1);100 }101 return;102 }103 }104 };105 106 const originalRequestFn = session.request;107 108 const {sessionTimeout} = options;109 110 if(sessionTimeout != null) {111 112 let timer;113 let streamsCount = 0;114 115 session.request = function () {116 const stream = originalRequestFn.apply(this, arguments);117 118 streamsCount++;119 120 if (timer) {121 clearTimeout(timer);122 timer = null;123 }124 125 stream.once('close', () => {126 if (!--streamsCount) {127 timer = setTimeout(() => {128 timer = null;129 removeSession();130 }, sessionTimeout);131 }132 });133 134 return stream;135 }136 }137 138 session.once('close', removeSession);139 140 let entry = [141 session,142 options143 ];144 145 authoritySessions ? authoritySessions.push(entry) : authoritySessions = this.sessions[authority] = [entry];146 147 return session;148 }149}150 151const http2Sessions = new Http2Sessions();152 153 154/**155 * If the proxy or config beforeRedirects functions are defined, call them with the options156 * object.157 *158 * @param {Object<string, any>} options - The options object that was passed to the request.159 *160 * @returns {Object<string, any>}161 */162function dispatchBeforeRedirect(options, responseDetails) {163 if (options.beforeRedirects.proxy) {164 options.beforeRedirects.proxy(options);165 }166 if (options.beforeRedirects.config) {167 options.beforeRedirects.config(options, responseDetails);168 }169}170 171/**172 * If the proxy or config afterRedirects functions are defined, call them with the options173 *174 * @param {http.ClientRequestArgs} options175 * @param {AxiosProxyConfig} configProxy configuration from Axios options object176 * @param {string} location177 *178 * @returns {http.ClientRequestArgs}179 */180function setProxy(options, configProxy, location) {181 let proxy = configProxy;182 if (!proxy && proxy !== false) {183 const proxyUrl = proxyFromEnv.getProxyForUrl(location);184 if (proxyUrl) {185 proxy = new URL(proxyUrl);186 }187 }188 if (proxy) {189 // Basic proxy authorization190 if (proxy.username) {191 proxy.auth = (proxy.username || '') + ':' + (proxy.password || '');192 }193 194 if (proxy.auth) {195 // Support proxy auth object form196 const validProxyAuth = Boolean(proxy.auth.username || proxy.auth.password);197 198 if (validProxyAuth) {199 proxy.auth = (proxy.auth.username || '') + ':' + (proxy.auth.password || '');200 } else if (typeof proxy.auth === 'object') {201 throw new AxiosError('Invalid proxy authorization', AxiosError.ERR_BAD_OPTION, { proxy });202 }203 204 const base64 = Buffer.from(proxy.auth, 'utf8').toString('base64');205 206 options.headers['Proxy-Authorization'] = 'Basic ' + base64;207 }208 209 options.headers.host = options.hostname + (options.port ? ':' + options.port : '');210 const proxyHost = proxy.hostname || proxy.host;211 options.hostname = proxyHost;212 // Replace 'host' since options is not a URL object213 options.host = proxyHost;214 options.port = proxy.port;215 options.path = location;216 if (proxy.protocol) {217 options.protocol = proxy.protocol.includes(':') ? proxy.protocol : `${proxy.protocol}:`;218 }219 }220 221 options.beforeRedirects.proxy = function beforeRedirect(redirectOptions) {222 // Configure proxy for redirected request, passing the original config proxy to apply223 // the exact same logic as if the redirected request was performed by axios directly.224 setProxy(redirectOptions, configProxy, redirectOptions.href);225 };226}227 228const isHttpAdapterSupported = typeof process !== 'undefined' && utils.kindOf(process) === 'process';229 230// temporary hotfix231 232const wrapAsync = (asyncExecutor) => {233 return new Promise((resolve, reject) => {234 let onDone;235 let isDone;236 237 const done = (value, isRejected) => {238 if (isDone) return;239 isDone = true;240 onDone && onDone(value, isRejected);241 }242 243 const _resolve = (value) => {244 done(value);245 resolve(value);246 };247 248 const _reject = (reason) => {249 done(reason, true);250 reject(reason);251 }252 253 asyncExecutor(_resolve, _reject, (onDoneHandler) => (onDone = onDoneHandler)).catch(_reject);254 })255};256 257const resolveFamily = ({address, family}) => {258 if (!utils.isString(address)) {259 throw TypeError('address must be a string');260 }261 return ({262 address,263 family: family || (address.indexOf('.') < 0 ? 6 : 4)264 });265}266 267const buildAddressEntry = (address, family) => resolveFamily(utils.isObject(address) ? address : {address, family});268 269const http2Transport = {270 request(options, cb) {271 const authority = options.protocol + '//' + options.hostname + ':' + (options.port ||(options.protocol === 'https:' ? 443 : 80));272 273 274 const {http2Options, headers} = options;275 276 const session = http2Sessions.getSession(authority, http2Options);277 278 const {279 HTTP2_HEADER_SCHEME,280 HTTP2_HEADER_METHOD,281 HTTP2_HEADER_PATH,282 HTTP2_HEADER_STATUS283 } = http2.constants;284 285 const http2Headers = {286 [HTTP2_HEADER_SCHEME]: options.protocol.replace(':', ''),287 [HTTP2_HEADER_METHOD]: options.method,288 [HTTP2_HEADER_PATH]: options.path,289 }290 291 utils.forEach(headers, (header, name) => {292 name.charAt(0) !== ':' && (http2Headers[name] = header);293 });294 295 const req = session.request(http2Headers);296 297 req.once('response', (responseHeaders) => {298 const response = req; //duplex299 300 responseHeaders = Object.assign({}, responseHeaders);301 302 const status = responseHeaders[HTTP2_HEADER_STATUS];303 304 delete responseHeaders[HTTP2_HEADER_STATUS];305 306 response.headers = responseHeaders;307 308 response.statusCode = +status;309 310 cb(response);311 })312 313 return req;314 }315}316 317/*eslint consistent-return:0*/318export default isHttpAdapterSupported && function httpAdapter(config) {319 return wrapAsync(async function dispatchHttpRequest(resolve, reject, onDone) {320 let {data, lookup, family, httpVersion = 1, http2Options} = config;321 const {responseType, responseEncoding} = config;322 const method = config.method.toUpperCase();323 let isDone;324 let rejected = false;325 let req;326 327 httpVersion = +httpVersion;328 329 if (Number.isNaN(httpVersion)) {330 throw TypeError(`Invalid protocol version: '${config.httpVersion}' is not a number`);331 }332 333 if (httpVersion !== 1 && httpVersion !== 2) {334 throw TypeError(`Unsupported protocol version '${httpVersion}'`);335 }336 337 const isHttp2 = httpVersion === 2;338 339 if (lookup) {340 const _lookup = callbackify(lookup, (value) => utils.isArray(value) ? value : [value]);341 // hotfix to support opt.all option which is required for node 20.x342 lookup = (hostname, opt, cb) => {343 _lookup(hostname, opt, (err, arg0, arg1) => {344 if (err) {345 return cb(err);346 }347 348 const addresses = utils.isArray(arg0) ? arg0.map(addr => buildAddressEntry(addr)) : [buildAddressEntry(arg0, arg1)];349 350 opt.all ? cb(err, addresses) : cb(err, addresses[0].address, addresses[0].family);351 });352 }353 }354 355 const abortEmitter = new EventEmitter();356 357 function abort(reason) {358 try {359 abortEmitter.emit('abort', !reason || reason.type ? new CanceledError(null, config, req) : reason);360 } catch(err) {361 console.warn('emit error', err);362 }363 }364 365 abortEmitter.once('abort', reject);366 367 const onFinished = () => {368 if (config.cancelToken) {369 config.cancelToken.unsubscribe(abort);370 }371 372 if (config.signal) {373 config.signal.removeEventListener('abort', abort);374 }375 376 abortEmitter.removeAllListeners();377 }378 379 if (config.cancelToken || config.signal) {380 config.cancelToken && config.cancelToken.subscribe(abort);381 if (config.signal) {382 config.signal.aborted ? abort() : config.signal.addEventListener('abort', abort);383 }384 }385 386 onDone((response, isRejected) => {387 isDone = true;388 389 if (isRejected) {390 rejected = true;391 onFinished();392 return;393 }394 395 const {data} = response;396 397 if (data instanceof stream.Readable || data instanceof stream.Duplex) {398 const offListeners = stream.finished(data, () => {399 offListeners();400 onFinished();401 });402 } else {403 onFinished();404 }405 });406 407 408 409 410 411 // Parse url412 const fullPath = buildFullPath(config.baseURL, config.url, config.allowAbsoluteUrls);413 const parsed = new URL(fullPath, platform.hasBrowserEnv ? platform.origin : undefined);414 const protocol = parsed.protocol || supportedProtocols[0];415 416 if (protocol === 'data:') {417 // Apply the same semantics as HTTP: only enforce if a finite, non-negative cap is set.418 if (config.maxContentLength > -1) {419 // Use the exact string passed to fromDataURI (config.url); fall back to fullPath if needed.420 const dataUrl = String(config.url || fullPath || '');421 const estimated = estimateDataURLDecodedBytes(dataUrl);422 423 if (estimated > config.maxContentLength) {424 return reject(new AxiosError(425 'maxContentLength size of ' + config.maxContentLength + ' exceeded',426 AxiosError.ERR_BAD_RESPONSE,427 config428 ));429 }430 }431 432 let convertedData;433 434 if (method !== 'GET') {435 return settle(resolve, reject, {436 status: 405,437 statusText: 'method not allowed',438 headers: {},439 config440 });441 }442 443 try {444 convertedData = fromDataURI(config.url, responseType === 'blob', {445 Blob: config.env && config.env.Blob446 });447 } catch (err) {448 throw AxiosError.from(err, AxiosError.ERR_BAD_REQUEST, config);449 }450 451 if (responseType === 'text') {452 convertedData = convertedData.toString(responseEncoding);453 454 if (!responseEncoding || responseEncoding === 'utf8') {455 convertedData = utils.stripBOM(convertedData);456 }457 } else if (responseType === 'stream') {458 convertedData = stream.Readable.from(convertedData);459 }460 461 return settle(resolve, reject, {462 data: convertedData,463 status: 200,464 statusText: 'OK',465 headers: new AxiosHeaders(),466 config467 });468 }469 470 if (supportedProtocols.indexOf(protocol) === -1) {471 return reject(new AxiosError(472 'Unsupported protocol ' + protocol,473 AxiosError.ERR_BAD_REQUEST,474 config475 ));476 }477 478 const headers = AxiosHeaders.from(config.headers).normalize();479 480 // Set User-Agent (required by some servers)481 // See https://github.com/axios/axios/issues/69482 // User-Agent is specified; handle case where no UA header is desired483 // Only set header if it hasn't been set in config484 headers.set('User-Agent', 'axios/' + VERSION, false);485 486 const {onUploadProgress, onDownloadProgress} = config;487 const maxRate = config.maxRate;488 let maxUploadRate = undefined;489 let maxDownloadRate = undefined;490 491 // support for spec compliant FormData objects492 if (utils.isSpecCompliantForm(data)) {493 const userBoundary = headers.getContentType(/boundary=([-_\w\d]{10,70})/i);494 495 data = formDataToStream(data, (formHeaders) => {496 headers.set(formHeaders);497 }, {498 tag: `axios-${VERSION}-boundary`,499 boundary: userBoundary && userBoundary[1] || undefined500 });501 // support for https://www.npmjs.com/package/form-data api502 } else if (utils.isFormData(data) && utils.isFunction(data.getHeaders)) {503 headers.set(data.getHeaders());504 505 if (!headers.hasContentLength()) {506 try {507 const knownLength = await util.promisify(data.getLength).call(data);508 Number.isFinite(knownLength) && knownLength >= 0 && headers.setContentLength(knownLength);509 /*eslint no-empty:0*/510 } catch (e) {511 }512 }513 } else if (utils.isBlob(data) || utils.isFile(data)) {514 data.size && headers.setContentType(data.type || 'application/octet-stream');515 headers.setContentLength(data.size || 0);516 data = stream.Readable.from(readBlob(data));517 } else if (data && !utils.isStream(data)) {518 if (Buffer.isBuffer(data)) {519 // Nothing to do...520 } else if (utils.isArrayBuffer(data)) {521 data = Buffer.from(new Uint8Array(data));522 } else if (utils.isString(data)) {523 data = Buffer.from(data, 'utf-8');524 } else {525 return reject(new AxiosError(526 'Data after transformation must be a string, an ArrayBuffer, a Buffer, or a Stream',527 AxiosError.ERR_BAD_REQUEST,528 config529 ));530 }531 532 // Add Content-Length header if data exists533 headers.setContentLength(data.length, false);534 535 if (config.maxBodyLength > -1 && data.length > config.maxBodyLength) {536 return reject(new AxiosError(537 'Request body larger than maxBodyLength limit',538 AxiosError.ERR_BAD_REQUEST,539 config540 ));541 }542 }543 544 const contentLength = utils.toFiniteNumber(headers.getContentLength());545 546 if (utils.isArray(maxRate)) {547 maxUploadRate = maxRate[0];548 maxDownloadRate = maxRate[1];549 } else {550 maxUploadRate = maxDownloadRate = maxRate;551 }552 553 if (data && (onUploadProgress || maxUploadRate)) {554 if (!utils.isStream(data)) {555 data = stream.Readable.from(data, {objectMode: false});556 }557 558 data = stream.pipeline([data, new AxiosTransformStream({559 maxRate: utils.toFiniteNumber(maxUploadRate)560 })], utils.noop);561 562 onUploadProgress && data.on('progress', flushOnFinish(563 data,564 progressEventDecorator(565 contentLength,566 progressEventReducer(asyncDecorator(onUploadProgress), false, 3)567 )568 ));569 }570 571 // HTTP basic authentication572 let auth = undefined;573 if (config.auth) {574 const username = config.auth.username || '';575 const password = config.auth.password || '';576 auth = username + ':' + password;577 }578 579 if (!auth && parsed.username) {580 const urlUsername = parsed.username;581 const urlPassword = parsed.password;582 auth = urlUsername + ':' + urlPassword;583 }584 585 auth && headers.delete('authorization');586 587 let path;588 589 try {590 path = buildURL(591 parsed.pathname + parsed.search,592 config.params,593 config.paramsSerializer594 ).replace(/^\?/, '');595 } catch (err) {596 const customErr = new Error(err.message);597 customErr.config = config;598 customErr.url = config.url;599 customErr.exists = true;600 return reject(customErr);601 }602 603 headers.set(604 'Accept-Encoding',605 'gzip, compress, deflate' + (isBrotliSupported ? ', br' : ''), false606 );607 608 const options = {609 path,610 method: method,611 headers: headers.toJSON(),612 agents: { http: config.httpAgent, https: config.httpsAgent },613 auth,614 protocol,615 family,616 beforeRedirect: dispatchBeforeRedirect,617 beforeRedirects: {},618 http2Options619 };620 621 // cacheable-lookup integration hotfix622 !utils.isUndefined(lookup) && (options.lookup = lookup);623 624 if (config.socketPath) {625 options.socketPath = config.socketPath;626 } else {627 options.hostname = parsed.hostname.startsWith("[") ? parsed.hostname.slice(1, -1) : parsed.hostname;628 options.port = parsed.port;629 setProxy(options, config.proxy, protocol + '//' + parsed.hostname + (parsed.port ? ':' + parsed.port : '') + options.path);630 }631 632 let transport;633 const isHttpsRequest = isHttps.test(options.protocol);634 options.agent = isHttpsRequest ? config.httpsAgent : config.httpAgent;635 636 if (isHttp2) {637 transport = http2Transport;638 } else {639 if (config.transport) {640 transport = config.transport;641 } else if (config.maxRedirects === 0) {642 transport = isHttpsRequest ? https : http;643 } else {644 if (config.maxRedirects) {645 options.maxRedirects = config.maxRedirects;646 }647 if (config.beforeRedirect) {648 options.beforeRedirects.config = config.beforeRedirect;649 }650 transport = isHttpsRequest ? httpsFollow : httpFollow;651 }652 }653 654 if (config.maxBodyLength > -1) {655 options.maxBodyLength = config.maxBodyLength;656 } else {657 // follow-redirects does not skip comparison, so it should always succeed for axios -1 unlimited658 options.maxBodyLength = Infinity;659 }660 661 if (config.insecureHTTPParser) {662 options.insecureHTTPParser = config.insecureHTTPParser;663 }664 665 // Create the request666 req = transport.request(options, function handleResponse(res) {667 if (req.destroyed) return;668 669 const streams = [res];670 671 const responseLength = utils.toFiniteNumber(res.headers['content-length']);672 673 if (onDownloadProgress || maxDownloadRate) {674 const transformStream = new AxiosTransformStream({675 maxRate: utils.toFiniteNumber(maxDownloadRate)676 });677 678 onDownloadProgress && transformStream.on('progress', flushOnFinish(679 transformStream,680 progressEventDecorator(681 responseLength,682 progressEventReducer(asyncDecorator(onDownloadProgress), true, 3)683 )684 ));685 686 streams.push(transformStream);687 }688 689 // decompress the response body transparently if required690 let responseStream = res;691 692 // return the last request in case of redirects693 const lastRequest = res.req || req;694 695 // if decompress disabled we should not decompress696 if (config.decompress !== false && res.headers['content-encoding']) {697 // if no content, but headers still say that it is encoded,698 // remove the header not confuse downstream operations699 if (method === 'HEAD' || res.statusCode === 204) {700 delete res.headers['content-encoding'];701 }702 703 switch ((res.headers['content-encoding'] || '').toLowerCase()) {704 /*eslint default-case:0*/705 case 'gzip':706 case 'x-gzip':707 case 'compress':708 case 'x-compress':709 // add the unzipper to the body stream processing pipeline710 streams.push(zlib.createUnzip(zlibOptions));711 712 // remove the content-encoding in order to not confuse downstream operations713 delete res.headers['content-encoding'];714 break;715 case 'deflate':716 streams.push(new ZlibHeaderTransformStream());717 718 // add the unzipper to the body stream processing pipeline719 streams.push(zlib.createUnzip(zlibOptions));720 721 // remove the content-encoding in order to not confuse downstream operations722 delete res.headers['content-encoding'];723 break;724 case 'br':725 if (isBrotliSupported) {726 streams.push(zlib.createBrotliDecompress(brotliOptions));727 delete res.headers['content-encoding'];728 }729 }730 }731 732 responseStream = streams.length > 1 ? stream.pipeline(streams, utils.noop) : streams[0];733 734 735 736 const response = {737 status: res.statusCode,738 statusText: res.statusMessage,739 headers: new AxiosHeaders(res.headers),740 config,741 request: lastRequest742 };743 744 if (responseType === 'stream') {745 response.data = responseStream;746 settle(resolve, reject, response);747 } else {748 const responseBuffer = [];749 let totalResponseBytes = 0;750 751 responseStream.on('data', function handleStreamData(chunk) {752 responseBuffer.push(chunk);753 totalResponseBytes += chunk.length;754 755 // make sure the content length is not over the maxContentLength if specified756 if (config.maxContentLength > -1 && totalResponseBytes > config.maxContentLength) {757 // stream.destroy() emit aborted event before calling reject() on Node.js v16758 rejected = true;759 responseStream.destroy();760 abort(new AxiosError('maxContentLength size of ' + config.maxContentLength + ' exceeded',761 AxiosError.ERR_BAD_RESPONSE, config, lastRequest));762 }763 });764 765 responseStream.on('aborted', function handlerStreamAborted() {766 if (rejected) {767 return;768 }769 770 const err = new AxiosError(771 'stream has been aborted',772 AxiosError.ERR_BAD_RESPONSE,773 config,774 lastRequest775 );776 responseStream.destroy(err);777 reject(err);778 });779 780 responseStream.on('error', function handleStreamError(err) {781 if (req.destroyed) return;782 reject(AxiosError.from(err, null, config, lastRequest));783 });784 785 responseStream.on('end', function handleStreamEnd() {786 try {787 let responseData = responseBuffer.length === 1 ? responseBuffer[0] : Buffer.concat(responseBuffer);788 if (responseType !== 'arraybuffer') {789 responseData = responseData.toString(responseEncoding);790 if (!responseEncoding || responseEncoding === 'utf8') {791 responseData = utils.stripBOM(responseData);792 }793 }794 response.data = responseData;795 } catch (err) {796 return reject(AxiosError.from(err, null, config, response.request, response));797 }798 settle(resolve, reject, response);799 });800 }801 802 abortEmitter.once('abort', err => {803 if (!responseStream.destroyed) {804 responseStream.emit('error', err);805 responseStream.destroy();806 }807 });808 });809 810 abortEmitter.once('abort', err => {811 if (req.close) {812 req.close();813 } else {814 req.destroy(err);815 }816 });817 818 // Handle errors819 req.on('error', function handleRequestError(err) {820 reject(AxiosError.from(err, null, config, req));821 });822 823 // set tcp keep alive to prevent drop connection by peer824 req.on('socket', function handleRequestSocket(socket) {825 // default interval of sending ack packet is 1 minute826 socket.setKeepAlive(true, 1000 * 60);827 });828 829 // Handle request timeout830 if (config.timeout) {831 // This is forcing a int timeout to avoid problems if the `req` interface doesn't handle other types.832 const timeout = parseInt(config.timeout, 10);833 834 if (Number.isNaN(timeout)) {835 abort(new AxiosError(836 'error trying to parse `config.timeout` to int',837 AxiosError.ERR_BAD_OPTION_VALUE,838 config,839 req840 ));841 842 return;843 }844 845 // Sometime, the response will be very slow, and does not respond, the connect event will be block by event loop system.846 // And timer callback will be fired, and abort() will be invoked before connection, then get "socket hang up" and code ECONNRESET.847 // 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.848 // And then these socket which be hang up will devouring CPU little by little.849 // ClientRequest.setTimeout will be fired on the specify milliseconds, and can make sure that abort() will be fired after connect.850 req.setTimeout(timeout, function handleRequestTimeout() {851 if (isDone) return;852 let timeoutErrorMessage = config.timeout ? 'timeout of ' + config.timeout + 'ms exceeded' : 'timeout exceeded';853 const transitional = config.transitional || transitionalDefaults;854 if (config.timeoutErrorMessage) {855 timeoutErrorMessage = config.timeoutErrorMessage;856 }857 abort(new AxiosError(858 timeoutErrorMessage,859 transitional.clarifyTimeoutError ? AxiosError.ETIMEDOUT : AxiosError.ECONNABORTED,860 config,861 req862 ));863 });864 } else {865 // explicitly reset the socket timeout value for a possible `keep-alive` request866 req.setTimeout(0);867 }868 869 870 // Send the request871 if (utils.isStream(data)) {872 let ended = false;873 let errored = false;874 875 data.on('end', () => {876 ended = true;877 });878 879 data.once('error', err => {880 errored = true;881 req.destroy(err);882 });883 884 data.on('close', () => {885 if (!ended && !errored) {886 abort(new CanceledError('Request stream has been aborted', config, req));887 }888 });889 890 data.pipe(req);891 } else {892 data && req.write(data);893 req.end();894 }895 });896}897 898export const __setProxy = setProxy;899 