123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- 'use strict';
- var utils = require('./../utils');
- var settle = require('./../core/settle');
- 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');
- /*eslint consistent-return:0*/
- module.exports = function httpAdapter(config) {
- return new Promise(function dispatchHttpRequest(resolve, reject) {
- var data = config.data;
- var headers = config.headers;
- var timer;
- // 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 = new Buffer(new Uint8Array(data));
- } else if (utils.isString(data)) {
- data = new Buffer(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 parsed = url.parse(config.url);
- 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 isHttps = protocol === 'https:';
- var agent = isHttps ? config.httpsAgent : config.httpAgent;
- var options = {
- hostname: parsed.hostname,
- port: parsed.port,
- path: buildURL(parsed.path, config.params, config.paramsSerializer).replace(/^\?/, ''),
- method: config.method,
- headers: headers,
- agent: agent,
- auth: auth
- };
- 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);
- 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 = new Buffer(proxy.auth.username + ':' + proxy.auth.password, 'utf8').toString('base64');
- options.headers['Proxy-Authorization'] = 'Basic ' + base64;
- }
- }
- var transport;
- if (config.transport) {
- transport = config.transport;
- } else if (config.maxRedirects === 0) {
- transport = isHttps ? https : http;
- } else {
- if (config.maxRedirects) {
- options.maxRedirects = config.maxRedirects;
- }
- transport = isHttps ? httpsFollow : httpFollow;
- }
- // Create the request
- var req = transport.request(options, function handleResponse(res) {
- if (req.aborted) return;
- // Response has been received so kill timer that handles request timeout
- clearTimeout(timer);
- timer = null;
- // 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 = 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) {
- 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('utf8');
- }
- 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 && !timer) {
- timer = setTimeout(function handleRequestTimeout() {
- req.abort();
- reject(createError('timeout of ' + config.timeout + 'ms exceeded', config, 'ECONNABORTED', req));
- }, config.timeout);
- }
- 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.pipe(req);
- } else {
- req.end(data);
- }
- });
- };
|