| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 | 'use strict';var utils = require('./../utils');var settle = require('./../core/settle');var buildFullPath = require('../core/buildFullPath');var buildURL = require('./../helpers/buildURL');var http = require('http');var https = require('https');var httpFollow = require('follow-redirects').http;var httpsFollow = require('follow-redirects').https;var url = require('url');var zlib = require('zlib');var pkg = require('./../../package.json');var createError = require('../core/createError');var enhanceError = require('../core/enhanceError');var isHttps = /https:?/;/*eslint consistent-return:0*/module.exports = function httpAdapter(config) {  return new Promise(function dispatchHttpRequest(resolvePromise, rejectPromise) {    var resolve = function resolve(value) {      resolvePromise(value);    };    var reject = function reject(value) {      rejectPromise(value);    };    var data = config.data;    var headers = config.headers;    // Set User-Agent (required by some servers)    // Only set header if it hasn't been set in config    // See https://github.com/axios/axios/issues/69    if (!headers['User-Agent'] && !headers['user-agent']) {      headers['User-Agent'] = 'axios/' + pkg.version;    }    if (data && !utils.isStream(data)) {      if (Buffer.isBuffer(data)) {        // Nothing to do...      } 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(createError(          'Data after transformation must be a string, an ArrayBuffer, a Buffer, or a Stream',          config        ));      }      // Add Content-Length header if data exists      headers['Content-Length'] = data.length;    }    // HTTP basic authentication    var auth = undefined;    if (config.auth) {      var username = config.auth.username || '';      var password = config.auth.password || '';      auth = username + ':' + password;    }    // Parse url    var fullPath = buildFullPath(config.baseURL, config.url);    var parsed = url.parse(fullPath);    var protocol = parsed.protocol || 'http:';    if (!auth && parsed.auth) {      var urlAuth = parsed.auth.split(':');      var urlUsername = urlAuth[0] || '';      var urlPassword = urlAuth[1] || '';      auth = urlUsername + ':' + urlPassword;    }    if (auth) {      delete headers.Authorization;    }    var isHttpsRequest = isHttps.test(protocol);    var agent = isHttpsRequest ? config.httpsAgent : config.httpAgent;    var options = {      path: buildURL(parsed.path, config.params, config.paramsSerializer).replace(/^\?/, ''),      method: config.method.toUpperCase(),      headers: headers,      agent: agent,      agents: { http: config.httpAgent, https: config.httpsAgent },      auth: auth    };    if (config.socketPath) {      options.socketPath = config.socketPath;    } else {      options.hostname = parsed.hostname;      options.port = parsed.port;    }    var proxy = config.proxy;    if (!proxy && proxy !== false) {      var proxyEnv = protocol.slice(0, -1) + '_proxy';      var proxyUrl = process.env[proxyEnv] || process.env[proxyEnv.toUpperCase()];      if (proxyUrl) {        var parsedProxyUrl = url.parse(proxyUrl);        var noProxyEnv = process.env.no_proxy || process.env.NO_PROXY;        var shouldProxy = true;        if (noProxyEnv) {          var noProxy = noProxyEnv.split(',').map(function trim(s) {            return s.trim();          });          shouldProxy = !noProxy.some(function proxyMatch(proxyElement) {            if (!proxyElement) {              return false;            }            if (proxyElement === '*') {              return true;            }            if (proxyElement[0] === '.' &&                parsed.hostname.substr(parsed.hostname.length - proxyElement.length) === proxyElement) {              return true;            }            return parsed.hostname === proxyElement;          });        }        if (shouldProxy) {          proxy = {            host: parsedProxyUrl.hostname,            port: parsedProxyUrl.port          };          if (parsedProxyUrl.auth) {            var proxyUrlAuth = parsedProxyUrl.auth.split(':');            proxy.auth = {              username: proxyUrlAuth[0],              password: proxyUrlAuth[1]            };          }        }      }    }    if (proxy) {      options.hostname = proxy.host;      options.host = proxy.host;      options.headers.host = parsed.hostname + (parsed.port ? ':' + parsed.port : '');      options.port = proxy.port;      options.path = protocol + '//' + parsed.hostname + (parsed.port ? ':' + parsed.port : '') + options.path;      // Basic proxy authorization      if (proxy.auth) {        var base64 = Buffer.from(proxy.auth.username + ':' + proxy.auth.password, 'utf8').toString('base64');        options.headers['Proxy-Authorization'] = 'Basic ' + base64;      }    }    var transport;    var isHttpsProxy = isHttpsRequest && (proxy ? isHttps.test(proxy.protocol) : true);    if (config.transport) {      transport = config.transport;    } else if (config.maxRedirects === 0) {      transport = isHttpsProxy ? https : http;    } else {      if (config.maxRedirects) {        options.maxRedirects = config.maxRedirects;      }      transport = isHttpsProxy ? httpsFollow : httpFollow;    }    if (config.maxContentLength && config.maxContentLength > -1) {      options.maxBodyLength = config.maxContentLength;    }    // Create the request    var req = transport.request(options, function handleResponse(res) {      if (req.aborted) return;      // uncompress the response body transparently if required      var stream = res;      switch (res.headers['content-encoding']) {      /*eslint default-case:0*/      case 'gzip':      case 'compress':      case 'deflate':        // add the unzipper to the body stream processing pipeline        stream = (res.statusCode === 204) ? stream : stream.pipe(zlib.createUnzip());        // remove the content-encoding in order to not confuse downstream operations        delete res.headers['content-encoding'];        break;      }      // return the last request in case of redirects      var lastRequest = res.req || req;      var response = {        status: res.statusCode,        statusText: res.statusMessage,        headers: res.headers,        config: config,        request: lastRequest      };      if (config.responseType === 'stream') {        response.data = stream;        settle(resolve, reject, response);      } else {        var responseBuffer = [];        stream.on('data', function handleStreamData(chunk) {          responseBuffer.push(chunk);          // make sure the content length is not over the maxContentLength if specified          if (config.maxContentLength > -1 && Buffer.concat(responseBuffer).length > config.maxContentLength) {            stream.destroy();            reject(createError('maxContentLength size of ' + config.maxContentLength + ' exceeded',              config, null, lastRequest));          }        });        stream.on('error', function handleStreamError(err) {          if (req.aborted) return;          reject(enhanceError(err, config, null, lastRequest));        });        stream.on('end', function handleStreamEnd() {          var responseData = Buffer.concat(responseBuffer);          if (config.responseType !== 'arraybuffer') {            responseData = responseData.toString(config.responseEncoding);          }          response.data = responseData;          settle(resolve, reject, response);        });      }    });    // Handle errors    req.on('error', function handleRequestError(err) {      if (req.aborted) return;      reject(enhanceError(err, config, null, req));    });    // Handle request timeout    if (config.timeout) {      // Sometime, the response will be very slow, and does not respond, the connect event will be block by event loop system.      // And timer callback will be fired, and abort() will be invoked before connection, then get "socket hang up" and code ECONNRESET.      // 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.      // And then these socket which be hang up will devoring CPU little by little.      // ClientRequest.setTimeout will be fired on the specify milliseconds, and can make sure that abort() will be fired after connect.      req.setTimeout(config.timeout, function handleRequestTimeout() {        req.abort();        reject(createError('timeout of ' + config.timeout + 'ms exceeded', config, 'ECONNABORTED', req));      });    }    if (config.cancelToken) {      // Handle cancellation      config.cancelToken.promise.then(function onCanceled(cancel) {        if (req.aborted) return;        req.abort();        reject(cancel);      });    }    // Send the request    if (utils.isStream(data)) {      data.on('error', function handleStreamError(err) {        reject(enhanceError(err, config, null, req));      }).pipe(req);    } else {      req.end(data);    }  });};
 |