项目原始demo,不改动
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
 
 
 
 

276 lines
8.5 KiB

  1. 'use strict';
  2. var utils = require('./../utils');
  3. var settle = require('./../core/settle');
  4. var buildURL = require('./../helpers/buildURL');
  5. var http = require('http');
  6. var https = require('https');
  7. var httpFollow = require('follow-redirects').http;
  8. var httpsFollow = require('follow-redirects').https;
  9. var url = require('url');
  10. var zlib = require('zlib');
  11. var pkg = require('./../../package.json');
  12. var createError = require('../core/createError');
  13. var enhanceError = require('../core/enhanceError');
  14. var isHttps = /https:?/;
  15. /*eslint consistent-return:0*/
  16. module.exports = function httpAdapter(config) {
  17. return new Promise(function dispatchHttpRequest(resolvePromise, rejectPromise) {
  18. var timer;
  19. var resolve = function resolve(value) {
  20. clearTimeout(timer);
  21. resolvePromise(value);
  22. };
  23. var reject = function reject(value) {
  24. clearTimeout(timer);
  25. rejectPromise(value);
  26. };
  27. var data = config.data;
  28. var headers = config.headers;
  29. // Set User-Agent (required by some servers)
  30. // Only set header if it hasn't been set in config
  31. // See https://github.com/axios/axios/issues/69
  32. if (!headers['User-Agent'] && !headers['user-agent']) {
  33. headers['User-Agent'] = 'axios/' + pkg.version;
  34. }
  35. if (data && !utils.isStream(data)) {
  36. if (Buffer.isBuffer(data)) {
  37. // Nothing to do...
  38. } else if (utils.isArrayBuffer(data)) {
  39. data = Buffer.from(new Uint8Array(data));
  40. } else if (utils.isString(data)) {
  41. data = Buffer.from(data, 'utf-8');
  42. } else {
  43. return reject(createError(
  44. 'Data after transformation must be a string, an ArrayBuffer, a Buffer, or a Stream',
  45. config
  46. ));
  47. }
  48. // Add Content-Length header if data exists
  49. headers['Content-Length'] = data.length;
  50. }
  51. // HTTP basic authentication
  52. var auth = undefined;
  53. if (config.auth) {
  54. var username = config.auth.username || '';
  55. var password = config.auth.password || '';
  56. auth = username + ':' + password;
  57. }
  58. // Parse url
  59. var parsed = url.parse(config.url);
  60. var protocol = parsed.protocol || 'http:';
  61. if (!auth && parsed.auth) {
  62. var urlAuth = parsed.auth.split(':');
  63. var urlUsername = urlAuth[0] || '';
  64. var urlPassword = urlAuth[1] || '';
  65. auth = urlUsername + ':' + urlPassword;
  66. }
  67. if (auth) {
  68. delete headers.Authorization;
  69. }
  70. var isHttpsRequest = isHttps.test(protocol);
  71. var agent = isHttpsRequest ? config.httpsAgent : config.httpAgent;
  72. var options = {
  73. path: buildURL(parsed.path, config.params, config.paramsSerializer).replace(/^\?/, ''),
  74. method: config.method.toUpperCase(),
  75. headers: headers,
  76. agent: agent,
  77. auth: auth
  78. };
  79. if (config.socketPath) {
  80. options.socketPath = config.socketPath;
  81. } else {
  82. options.hostname = parsed.hostname;
  83. options.port = parsed.port;
  84. }
  85. var proxy = config.proxy;
  86. if (!proxy && proxy !== false) {
  87. var proxyEnv = protocol.slice(0, -1) + '_proxy';
  88. var proxyUrl = process.env[proxyEnv] || process.env[proxyEnv.toUpperCase()];
  89. if (proxyUrl) {
  90. var parsedProxyUrl = url.parse(proxyUrl);
  91. var noProxyEnv = process.env.no_proxy || process.env.NO_PROXY;
  92. var shouldProxy = true;
  93. if (noProxyEnv) {
  94. var noProxy = noProxyEnv.split(',').map(function trim(s) {
  95. return s.trim();
  96. });
  97. shouldProxy = !noProxy.some(function proxyMatch(proxyElement) {
  98. if (!proxyElement) {
  99. return false;
  100. }
  101. if (proxyElement === '*') {
  102. return true;
  103. }
  104. if (proxyElement[0] === '.' &&
  105. parsed.hostname.substr(parsed.hostname.length - proxyElement.length) === proxyElement &&
  106. proxyElement.match(/\./g).length === parsed.hostname.match(/\./g).length) {
  107. return true;
  108. }
  109. return parsed.hostname === proxyElement;
  110. });
  111. }
  112. if (shouldProxy) {
  113. proxy = {
  114. host: parsedProxyUrl.hostname,
  115. port: parsedProxyUrl.port
  116. };
  117. if (parsedProxyUrl.auth) {
  118. var proxyUrlAuth = parsedProxyUrl.auth.split(':');
  119. proxy.auth = {
  120. username: proxyUrlAuth[0],
  121. password: proxyUrlAuth[1]
  122. };
  123. }
  124. }
  125. }
  126. }
  127. if (proxy) {
  128. options.hostname = proxy.host;
  129. options.host = proxy.host;
  130. options.headers.host = parsed.hostname + (parsed.port ? ':' + parsed.port : '');
  131. options.port = proxy.port;
  132. options.path = protocol + '//' + parsed.hostname + (parsed.port ? ':' + parsed.port : '') + options.path;
  133. // Basic proxy authorization
  134. if (proxy.auth) {
  135. var base64 = Buffer.from(proxy.auth.username + ':' + proxy.auth.password, 'utf8').toString('base64');
  136. options.headers['Proxy-Authorization'] = 'Basic ' + base64;
  137. }
  138. }
  139. var transport;
  140. var isHttpsProxy = isHttpsRequest && (proxy ? isHttps.test(proxy.protocol) : true);
  141. if (config.transport) {
  142. transport = config.transport;
  143. } else if (config.maxRedirects === 0) {
  144. transport = isHttpsProxy ? https : http;
  145. } else {
  146. if (config.maxRedirects) {
  147. options.maxRedirects = config.maxRedirects;
  148. }
  149. transport = isHttpsProxy ? httpsFollow : httpFollow;
  150. }
  151. if (config.maxContentLength && config.maxContentLength > -1) {
  152. options.maxBodyLength = config.maxContentLength;
  153. }
  154. // Create the request
  155. var req = transport.request(options, function handleResponse(res) {
  156. if (req.aborted) return;
  157. // uncompress the response body transparently if required
  158. var stream = res;
  159. switch (res.headers['content-encoding']) {
  160. /*eslint default-case:0*/
  161. case 'gzip':
  162. case 'compress':
  163. case 'deflate':
  164. // add the unzipper to the body stream processing pipeline
  165. stream = (res.statusCode === 204) ? stream : stream.pipe(zlib.createUnzip());
  166. // remove the content-encoding in order to not confuse downstream operations
  167. delete res.headers['content-encoding'];
  168. break;
  169. }
  170. // return the last request in case of redirects
  171. var lastRequest = res.req || req;
  172. var response = {
  173. status: res.statusCode,
  174. statusText: res.statusMessage,
  175. headers: res.headers,
  176. config: config,
  177. request: lastRequest
  178. };
  179. if (config.responseType === 'stream') {
  180. response.data = stream;
  181. settle(resolve, reject, response);
  182. } else {
  183. var responseBuffer = [];
  184. stream.on('data', function handleStreamData(chunk) {
  185. responseBuffer.push(chunk);
  186. // make sure the content length is not over the maxContentLength if specified
  187. if (config.maxContentLength > -1 && Buffer.concat(responseBuffer).length > config.maxContentLength) {
  188. stream.destroy();
  189. reject(createError('maxContentLength size of ' + config.maxContentLength + ' exceeded',
  190. config, null, lastRequest));
  191. }
  192. });
  193. stream.on('error', function handleStreamError(err) {
  194. if (req.aborted) return;
  195. reject(enhanceError(err, config, null, lastRequest));
  196. });
  197. stream.on('end', function handleStreamEnd() {
  198. var responseData = Buffer.concat(responseBuffer);
  199. if (config.responseType !== 'arraybuffer') {
  200. responseData = responseData.toString(config.responseEncoding);
  201. }
  202. response.data = responseData;
  203. settle(resolve, reject, response);
  204. });
  205. }
  206. });
  207. // Handle errors
  208. req.on('error', function handleRequestError(err) {
  209. if (req.aborted) return;
  210. reject(enhanceError(err, config, null, req));
  211. });
  212. // Handle request timeout
  213. if (config.timeout) {
  214. timer = setTimeout(function handleRequestTimeout() {
  215. req.abort();
  216. reject(createError('timeout of ' + config.timeout + 'ms exceeded', config, 'ECONNABORTED', req));
  217. }, config.timeout);
  218. }
  219. if (config.cancelToken) {
  220. // Handle cancellation
  221. config.cancelToken.promise.then(function onCanceled(cancel) {
  222. if (req.aborted) return;
  223. req.abort();
  224. reject(cancel);
  225. });
  226. }
  227. // Send the request
  228. if (utils.isStream(data)) {
  229. data.on('error', function handleStreamError(err) {
  230. reject(enhanceError(err, config, null, req));
  231. }).pipe(req);
  232. } else {
  233. req.end(data);
  234. }
  235. });
  236. };