request.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. "use strict";
  2. var __importDefault = (this && this.__importDefault) || function (mod) {
  3. return (mod && mod.__esModule) ? mod : { "default": mod };
  4. };
  5. var __importStar = (this && this.__importStar) || function (mod) {
  6. if (mod && mod.__esModule) return mod;
  7. var result = {};
  8. if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
  9. result["default"] = mod;
  10. return result;
  11. };
  12. Object.defineProperty(exports, "__esModule", { value: true });
  13. const http_1 = __importDefault(require("http"));
  14. const request_1 = __importDefault(require("request"));
  15. const retry_1 = require("./retry");
  16. const request_timings_measurer_1 = require("./request-timings-measurer");
  17. const agentkeepalive_1 = __importStar(require("agentkeepalive"));
  18. const SAFE_RETRY_CODE_SET = new Set([
  19. 'ENOTFOUND',
  20. 'ENETDOWN',
  21. 'EHOSTDOWN',
  22. 'ENETUNREACH',
  23. 'EHOSTUNREACH',
  24. 'ECONNREFUSED'
  25. ]);
  26. const RETRY_CODE_SET = new Set(['ECONNRESET', 'ESOCKETTIMEDOUT']);
  27. const RETRY_STATUS_CODE_SET = new Set([]);
  28. /* istanbul ignore next */
  29. function shouldRetry(e, result, operation) {
  30. // 重试的错误码
  31. if (e && SAFE_RETRY_CODE_SET.has(e.code)) {
  32. return {
  33. retryAble: true,
  34. message: e.message
  35. };
  36. }
  37. // 连接超时
  38. if (e && e.code === 'ETIMEDOUT' && e.connect === true) {
  39. return {
  40. retryAble: true,
  41. message: e.message
  42. };
  43. }
  44. // 重试的状态码
  45. if (result && RETRY_STATUS_CODE_SET.has(result.statusCode)) {
  46. return {
  47. retryAble: true,
  48. message: `${result.request.method} ${result.request.href} ${result.statusCode} ${http_1.default.STATUS_CODES[result.statusCode]}`
  49. };
  50. }
  51. return {
  52. retryAble: false,
  53. message: ''
  54. };
  55. }
  56. /* istanbul ignore next */
  57. function requestWithTimingsMeasure(opts, extraOptions) {
  58. return new Promise((resolve, reject) => {
  59. const timingsMeasurerOptions = extraOptions.timingsMeasurerOptions || {};
  60. const { waitingTime = 1000, interval = 200, enable = !!extraOptions.debug } = timingsMeasurerOptions;
  61. const timingsMeasurer = request_timings_measurer_1.RequestTimgingsMeasurer.new({
  62. waitingTime,
  63. interval,
  64. enable
  65. });
  66. timingsMeasurer.on('progress', (timings, reason = '') => {
  67. const timingsLine = `s:${timings.socket || '-'}|l:${timings.lookup ||
  68. '-'}|c:${timings.connect || '-'}|r:${timings.ready || '-'}|w:${timings.waiting ||
  69. '-'}|d:${timings.download || '-'}|e:${timings.end || '-'}|E:${timings.error || '-'}`;
  70. console.warn(`[RequestTimgings][${extraOptions.op || ''}] spent ${Date.now() -
  71. timings.start}ms(${timingsLine}) [${extraOptions.seqId}][${extraOptions.attempts || 1}][${reason}]`);
  72. });
  73. if (opts.keepalive) {
  74. ;
  75. opts.agentClass = opts.url.startsWith('https')
  76. ? agentkeepalive_1.HttpsAgent
  77. : agentkeepalive_1.default;
  78. opts.agentOptions = {
  79. // keepAlive: true,
  80. keepAliveMsecs: 3000,
  81. maxSockets: 100,
  82. maxFreeSockets: 10,
  83. freeSocketTimeout: 20000,
  84. timeout: 20000,
  85. socketActiveTTL: null
  86. };
  87. }
  88. ;
  89. (function r(times) {
  90. const clientRequest = request_1.default(opts, function (err, response, body) {
  91. const reusedSocket = !!(clientRequest && clientRequest.req && clientRequest.req.reusedSocket);
  92. if (err && err.code === 'ECONNRESET' && reusedSocket && times >= 0 && opts.keepalive) {
  93. return r(--times);
  94. }
  95. return err ? reject(err) : resolve(response);
  96. });
  97. if ((request_1.default.Request && clientRequest instanceof request_1.default.Request) ||
  98. clientRequest instanceof http_1.default.ClientRequest) {
  99. timingsMeasurer.measure(clientRequest);
  100. }
  101. }(1));
  102. });
  103. }
  104. exports.requestWithTimingsMeasure = requestWithTimingsMeasure;
  105. function extraRequest(opts, extraOptions) {
  106. if (extraOptions && extraOptions.retryOptions) {
  107. return retry_1.withRetry(attempts => {
  108. return requestWithTimingsMeasure(opts, Object.assign({}, extraOptions, { attempts }));
  109. }, Object.assign({ shouldRetry }, extraOptions.retryOptions));
  110. }
  111. else {
  112. return requestWithTimingsMeasure(opts, Object.assign({}, extraOptions, { attempts: 1 }));
  113. }
  114. }
  115. exports.extraRequest = extraRequest;