rezo 1.0.19 → 1.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/adapters/curl.cjs +39 -34
  2. package/dist/adapters/curl.js +39 -34
  3. package/dist/adapters/entries/curl.d.ts +19 -18
  4. package/dist/adapters/entries/fetch.d.ts +19 -18
  5. package/dist/adapters/entries/http.d.ts +19 -18
  6. package/dist/adapters/entries/http2.d.ts +19 -18
  7. package/dist/adapters/entries/react-native.d.ts +19 -18
  8. package/dist/adapters/entries/xhr.d.ts +19 -18
  9. package/dist/adapters/fetch.cjs +42 -41
  10. package/dist/adapters/fetch.js +42 -41
  11. package/dist/adapters/http.cjs +65 -46
  12. package/dist/adapters/http.js +65 -46
  13. package/dist/adapters/http2.cjs +41 -36
  14. package/dist/adapters/http2.js +41 -36
  15. package/dist/adapters/index.cjs +6 -6
  16. package/dist/adapters/react-native.cjs +41 -27
  17. package/dist/adapters/react-native.js +41 -27
  18. package/dist/adapters/xhr.cjs +43 -38
  19. package/dist/adapters/xhr.js +43 -38
  20. package/dist/cache/index.cjs +13 -13
  21. package/dist/crawler.d.ts +19 -18
  22. package/dist/entries/crawler.cjs +5 -5
  23. package/dist/errors/rezo-error.cjs +139 -21
  24. package/dist/errors/rezo-error.js +138 -21
  25. package/dist/index.cjs +24 -24
  26. package/dist/index.d.ts +19 -18
  27. package/dist/platform/browser.d.ts +19 -18
  28. package/dist/platform/bun.d.ts +19 -18
  29. package/dist/platform/deno.d.ts +19 -18
  30. package/dist/platform/node.d.ts +19 -18
  31. package/dist/platform/react-native.d.ts +19 -18
  32. package/dist/platform/worker.d.ts +19 -18
  33. package/dist/plugin/index.cjs +36 -36
  34. package/dist/proxy/index.cjs +2 -2
  35. package/dist/queue/index.cjs +8 -8
  36. package/dist/utils/http-config.cjs +6 -3
  37. package/dist/utils/http-config.js +6 -3
  38. package/dist/utils/timing.cjs +90 -0
  39. package/dist/utils/timing.js +78 -0
  40. package/package.json +1 -1
@@ -28,6 +28,30 @@ const Environment = {
28
28
  return typeof AbortController !== "undefined";
29
29
  }
30
30
  };
31
+ function updateTiming(config, timing, bodySize) {
32
+ const now = performance.now();
33
+ config.timing.domainLookupStart = config.timing.startTime;
34
+ config.timing.domainLookupEnd = config.timing.startTime;
35
+ config.timing.connectStart = config.timing.startTime;
36
+ config.timing.secureConnectionStart = 0;
37
+ config.timing.connectEnd = config.timing.startTime;
38
+ config.timing.requestStart = config.timing.startTime;
39
+ config.timing.responseStart = timing.firstByteTime || config.timing.startTime;
40
+ config.timing.responseEnd = now;
41
+ config.transfer.bodySize = bodySize;
42
+ config.transfer.responseSize = bodySize;
43
+ }
44
+ function getTimingDurations(config) {
45
+ const t = config.timing;
46
+ return {
47
+ total: t.responseEnd - t.startTime,
48
+ dns: t.domainLookupEnd - t.domainLookupStart,
49
+ tcp: t.secureConnectionStart > 0 ? t.secureConnectionStart - t.connectStart : t.connectEnd - t.connectStart,
50
+ tls: t.secureConnectionStart > 0 ? t.connectEnd - t.secureConnectionStart : undefined,
51
+ firstByte: t.responseStart - t.startTime,
52
+ download: t.responseEnd - t.responseStart
53
+ };
54
+ }
31
55
  const responseCacheInstances = new Map;
32
56
  function getCacheConfigKey(option) {
33
57
  if (option === true)
@@ -314,10 +338,11 @@ async function executeFetchRequest(fetchOptions, config, options, perform, strea
314
338
  const maxRetries = config?.retry?.maxRetries || 0;
315
339
  const incrementDelay = config?.retry?.incrementDelay || false;
316
340
  const statusCodes = config?.retry?.statusCodes;
341
+ const startTime = performance.now();
317
342
  const timing = {
318
- startTime: performance.now(),
319
- startTimestamp: Date.now()
343
+ startTime
320
344
  };
345
+ config.timing.startTime = startTime;
321
346
  const ABSOLUTE_MAX_ATTEMPTS = 50;
322
347
  const visitedUrls = new Set;
323
348
  let totalAttempts = 0;
@@ -471,7 +496,6 @@ async function executeSingleFetchRequest(config, fetchOptions, requestCount, tim
471
496
  config.finalUrl = url.href;
472
497
  config.network.protocol = isSecure ? "https" : "http";
473
498
  config.network.httpVersion = undefined;
474
- config.timing.startTimestamp = timing.startTimestamp;
475
499
  if (!config.transfer) {
476
500
  config.transfer = { requestSize: 0, responseSize: 0, headerSize: 0, bodySize: 0 };
477
501
  } else if (config.transfer.requestSize === undefined) {
@@ -550,9 +574,9 @@ async function executeSingleFetchRequest(config, fetchOptions, requestCount, tim
550
574
  if (timeoutId)
551
575
  clearTimeout(timeoutId);
552
576
  }
553
- if (!config.timing.ttfbMs) {
577
+ if (!timing.firstByteTime) {
554
578
  timing.firstByteTime = performance.now();
555
- config.timing.ttfbMs = timing.firstByteTime - timing.startTime;
579
+ config.timing.responseStart = timing.firstByteTime;
556
580
  }
557
581
  const status = response.status;
558
582
  const statusText = response.statusText;
@@ -589,8 +613,8 @@ async function executeSingleFetchRequest(config, fetchOptions, requestCount, tim
589
613
  contentLength: contentLength ? parseInt(contentLength, 10) : undefined,
590
614
  cookies: cookies.array,
591
615
  timing: {
592
- firstByte: config.timing.ttfbMs,
593
- total: performance.now() - timing.startTime
616
+ firstByte: config.timing.responseStart - config.timing.startTime,
617
+ total: performance.now() - config.timing.startTime
594
618
  }
595
619
  };
596
620
  eventEmitter.emit("headers", headersEvent);
@@ -635,12 +659,8 @@ async function executeSingleFetchRequest(config, fetchOptions, requestCount, tim
635
659
  responseData = await response.text();
636
660
  }
637
661
  }
638
- config.timing.endTimestamp = Date.now();
639
- config.timing.durationMs = performance.now() - timing.startTime;
640
- config.timing.transferMs = timing.firstByteTime ? performance.now() - timing.firstByteTime : config.timing.durationMs;
641
662
  const bodySize = bodyBuffer?.byteLength || (typeof responseData === "string" ? responseData.length : 0);
642
- config.transfer.bodySize = bodySize;
643
- config.transfer.responseSize = bodySize;
663
+ updateTiming(config, timing, bodySize);
644
664
  config.status = status;
645
665
  config.statusText = statusText;
646
666
  _stats.statusOnNext = status >= 400 ? "error" : "success";
@@ -674,14 +694,10 @@ async function executeSingleFetchRequest(config, fetchOptions, requestCount, tim
674
694
  fileName: config.fileName,
675
695
  fileSize: buffer.length,
676
696
  timing: {
677
- total: config.timing.durationMs || 0,
678
- dns: config.timing.dnsMs,
679
- tcp: config.timing.tcpMs,
680
- tls: config.timing.tlsMs,
681
- firstByte: config.timing.ttfbMs,
682
- download: config.timing.transferMs || 0
697
+ ...getTimingDurations(config),
698
+ download: getTimingDurations(config).download || 0
683
699
  },
684
- averageSpeed: config.timing.transferMs ? buffer.length / config.timing.transferMs * 1000 : 0,
700
+ averageSpeed: getTimingDurations(config).download ? buffer.length / getTimingDurations(config).download * 1000 : 0,
685
701
  config: sanitizeConfig(config)
686
702
  };
687
703
  downloadResult.emit("finish", downloadFinishEvent);
@@ -720,16 +736,12 @@ async function executeSingleFetchRequest(config, fetchOptions, requestCount, tim
720
736
  urls: buildUrlTree(config, url.href),
721
737
  uploadSize: config.transfer.requestSize || 0,
722
738
  timing: {
723
- total: config.timing.durationMs || 0,
724
- dns: config.timing.dnsMs,
725
- tcp: config.timing.tcpMs,
726
- tls: config.timing.tlsMs,
727
- upload: config.timing.transferMs || 0,
728
- waiting: config.timing.ttfbMs || 0,
729
- download: config.timing.transferMs
739
+ ...getTimingDurations(config),
740
+ upload: getTimingDurations(config).firstByte || 0,
741
+ waiting: getTimingDurations(config).download > 0 && getTimingDurations(config).firstByte > 0 ? getTimingDurations(config).download - getTimingDurations(config).firstByte : 0
730
742
  },
731
- averageUploadSpeed: config.timing.transferMs ? (config.transfer.requestSize || 0) / config.timing.transferMs * 1000 : 0,
732
- averageDownloadSpeed: config.timing.transferMs ? bodySize / config.timing.transferMs * 1000 : 0,
743
+ averageUploadSpeed: getTimingDurations(config).firstByte && config.transfer.requestSize ? config.transfer.requestSize / getTimingDurations(config).firstByte * 1000 : 0,
744
+ averageDownloadSpeed: getTimingDurations(config).download ? bodySize / getTimingDurations(config).download * 1000 : 0,
733
745
  config: sanitizeConfig(config)
734
746
  };
735
747
  uploadResult.emit("finish", uploadFinishEvent);
@@ -777,11 +789,7 @@ async function handleStreamingResponse(response, config, timing, streamResult, u
777
789
  streamResult.emit("download-progress", progressEvent);
778
790
  }
779
791
  }
780
- config.timing.endTimestamp = Date.now();
781
- config.timing.durationMs = performance.now() - timing.startTime;
782
- config.timing.transferMs = timing.firstByteTime ? performance.now() - timing.firstByteTime : config.timing.durationMs;
783
- config.transfer.bodySize = bytesReceived;
784
- config.transfer.responseSize = bytesReceived;
792
+ updateTiming(config, timing, bytesReceived);
785
793
  const streamFinishEvent = {
786
794
  status,
787
795
  statusText,
@@ -791,14 +799,7 @@ async function handleStreamingResponse(response, config, timing, streamResult, u
791
799
  finalUrl: url.href,
792
800
  cookies,
793
801
  urls: buildUrlTree(config, url.href),
794
- timing: {
795
- total: config.timing.durationMs || 0,
796
- dns: config.timing.dnsMs,
797
- tcp: config.timing.tcpMs,
798
- tls: config.timing.tlsMs,
799
- firstByte: config.timing.ttfbMs,
800
- download: config.timing.transferMs
801
- },
802
+ timing: getTimingDurations(config),
802
803
  config: sanitizeConfig(config)
803
804
  };
804
805
  streamResult.emit("finish", streamFinishEvent);
@@ -28,6 +28,30 @@ const Environment = {
28
28
  return typeof AbortController !== "undefined";
29
29
  }
30
30
  };
31
+ function updateTiming(config, timing, bodySize) {
32
+ const now = performance.now();
33
+ config.timing.domainLookupStart = config.timing.startTime;
34
+ config.timing.domainLookupEnd = config.timing.startTime;
35
+ config.timing.connectStart = config.timing.startTime;
36
+ config.timing.secureConnectionStart = 0;
37
+ config.timing.connectEnd = config.timing.startTime;
38
+ config.timing.requestStart = config.timing.startTime;
39
+ config.timing.responseStart = timing.firstByteTime || config.timing.startTime;
40
+ config.timing.responseEnd = now;
41
+ config.transfer.bodySize = bodySize;
42
+ config.transfer.responseSize = bodySize;
43
+ }
44
+ function getTimingDurations(config) {
45
+ const t = config.timing;
46
+ return {
47
+ total: t.responseEnd - t.startTime,
48
+ dns: t.domainLookupEnd - t.domainLookupStart,
49
+ tcp: t.secureConnectionStart > 0 ? t.secureConnectionStart - t.connectStart : t.connectEnd - t.connectStart,
50
+ tls: t.secureConnectionStart > 0 ? t.connectEnd - t.secureConnectionStart : undefined,
51
+ firstByte: t.responseStart - t.startTime,
52
+ download: t.responseEnd - t.responseStart
53
+ };
54
+ }
31
55
  const responseCacheInstances = new Map;
32
56
  function getCacheConfigKey(option) {
33
57
  if (option === true)
@@ -314,10 +338,11 @@ async function executeFetchRequest(fetchOptions, config, options, perform, strea
314
338
  const maxRetries = config?.retry?.maxRetries || 0;
315
339
  const incrementDelay = config?.retry?.incrementDelay || false;
316
340
  const statusCodes = config?.retry?.statusCodes;
341
+ const startTime = performance.now();
317
342
  const timing = {
318
- startTime: performance.now(),
319
- startTimestamp: Date.now()
343
+ startTime
320
344
  };
345
+ config.timing.startTime = startTime;
321
346
  const ABSOLUTE_MAX_ATTEMPTS = 50;
322
347
  const visitedUrls = new Set;
323
348
  let totalAttempts = 0;
@@ -471,7 +496,6 @@ async function executeSingleFetchRequest(config, fetchOptions, requestCount, tim
471
496
  config.finalUrl = url.href;
472
497
  config.network.protocol = isSecure ? "https" : "http";
473
498
  config.network.httpVersion = undefined;
474
- config.timing.startTimestamp = timing.startTimestamp;
475
499
  if (!config.transfer) {
476
500
  config.transfer = { requestSize: 0, responseSize: 0, headerSize: 0, bodySize: 0 };
477
501
  } else if (config.transfer.requestSize === undefined) {
@@ -550,9 +574,9 @@ async function executeSingleFetchRequest(config, fetchOptions, requestCount, tim
550
574
  if (timeoutId)
551
575
  clearTimeout(timeoutId);
552
576
  }
553
- if (!config.timing.ttfbMs) {
577
+ if (!timing.firstByteTime) {
554
578
  timing.firstByteTime = performance.now();
555
- config.timing.ttfbMs = timing.firstByteTime - timing.startTime;
579
+ config.timing.responseStart = timing.firstByteTime;
556
580
  }
557
581
  const status = response.status;
558
582
  const statusText = response.statusText;
@@ -589,8 +613,8 @@ async function executeSingleFetchRequest(config, fetchOptions, requestCount, tim
589
613
  contentLength: contentLength ? parseInt(contentLength, 10) : undefined,
590
614
  cookies: cookies.array,
591
615
  timing: {
592
- firstByte: config.timing.ttfbMs,
593
- total: performance.now() - timing.startTime
616
+ firstByte: config.timing.responseStart - config.timing.startTime,
617
+ total: performance.now() - config.timing.startTime
594
618
  }
595
619
  };
596
620
  eventEmitter.emit("headers", headersEvent);
@@ -635,12 +659,8 @@ async function executeSingleFetchRequest(config, fetchOptions, requestCount, tim
635
659
  responseData = await response.text();
636
660
  }
637
661
  }
638
- config.timing.endTimestamp = Date.now();
639
- config.timing.durationMs = performance.now() - timing.startTime;
640
- config.timing.transferMs = timing.firstByteTime ? performance.now() - timing.firstByteTime : config.timing.durationMs;
641
662
  const bodySize = bodyBuffer?.byteLength || (typeof responseData === "string" ? responseData.length : 0);
642
- config.transfer.bodySize = bodySize;
643
- config.transfer.responseSize = bodySize;
663
+ updateTiming(config, timing, bodySize);
644
664
  config.status = status;
645
665
  config.statusText = statusText;
646
666
  _stats.statusOnNext = status >= 400 ? "error" : "success";
@@ -674,14 +694,10 @@ async function executeSingleFetchRequest(config, fetchOptions, requestCount, tim
674
694
  fileName: config.fileName,
675
695
  fileSize: buffer.length,
676
696
  timing: {
677
- total: config.timing.durationMs || 0,
678
- dns: config.timing.dnsMs,
679
- tcp: config.timing.tcpMs,
680
- tls: config.timing.tlsMs,
681
- firstByte: config.timing.ttfbMs,
682
- download: config.timing.transferMs || 0
697
+ ...getTimingDurations(config),
698
+ download: getTimingDurations(config).download || 0
683
699
  },
684
- averageSpeed: config.timing.transferMs ? buffer.length / config.timing.transferMs * 1000 : 0,
700
+ averageSpeed: getTimingDurations(config).download ? buffer.length / getTimingDurations(config).download * 1000 : 0,
685
701
  config: sanitizeConfig(config)
686
702
  };
687
703
  downloadResult.emit("finish", downloadFinishEvent);
@@ -720,16 +736,12 @@ async function executeSingleFetchRequest(config, fetchOptions, requestCount, tim
720
736
  urls: buildUrlTree(config, url.href),
721
737
  uploadSize: config.transfer.requestSize || 0,
722
738
  timing: {
723
- total: config.timing.durationMs || 0,
724
- dns: config.timing.dnsMs,
725
- tcp: config.timing.tcpMs,
726
- tls: config.timing.tlsMs,
727
- upload: config.timing.transferMs || 0,
728
- waiting: config.timing.ttfbMs || 0,
729
- download: config.timing.transferMs
739
+ ...getTimingDurations(config),
740
+ upload: getTimingDurations(config).firstByte || 0,
741
+ waiting: getTimingDurations(config).download > 0 && getTimingDurations(config).firstByte > 0 ? getTimingDurations(config).download - getTimingDurations(config).firstByte : 0
730
742
  },
731
- averageUploadSpeed: config.timing.transferMs ? (config.transfer.requestSize || 0) / config.timing.transferMs * 1000 : 0,
732
- averageDownloadSpeed: config.timing.transferMs ? bodySize / config.timing.transferMs * 1000 : 0,
743
+ averageUploadSpeed: getTimingDurations(config).firstByte && config.transfer.requestSize ? config.transfer.requestSize / getTimingDurations(config).firstByte * 1000 : 0,
744
+ averageDownloadSpeed: getTimingDurations(config).download ? bodySize / getTimingDurations(config).download * 1000 : 0,
733
745
  config: sanitizeConfig(config)
734
746
  };
735
747
  uploadResult.emit("finish", uploadFinishEvent);
@@ -777,11 +789,7 @@ async function handleStreamingResponse(response, config, timing, streamResult, u
777
789
  streamResult.emit("download-progress", progressEvent);
778
790
  }
779
791
  }
780
- config.timing.endTimestamp = Date.now();
781
- config.timing.durationMs = performance.now() - timing.startTime;
782
- config.timing.transferMs = timing.firstByteTime ? performance.now() - timing.firstByteTime : config.timing.durationMs;
783
- config.transfer.bodySize = bytesReceived;
784
- config.transfer.responseSize = bytesReceived;
792
+ updateTiming(config, timing, bytesReceived);
785
793
  const streamFinishEvent = {
786
794
  status,
787
795
  statusText,
@@ -791,14 +799,7 @@ async function handleStreamingResponse(response, config, timing, streamResult, u
791
799
  finalUrl: url.href,
792
800
  cookies,
793
801
  urls: buildUrlTree(config, url.href),
794
- timing: {
795
- total: config.timing.durationMs || 0,
796
- dns: config.timing.dnsMs,
797
- tcp: config.timing.tcpMs,
798
- tls: config.timing.tlsMs,
799
- firstByte: config.timing.ttfbMs,
800
- download: config.timing.transferMs
801
- },
802
+ timing: getTimingDurations(config),
802
803
  config: sanitizeConfig(config)
803
804
  };
804
805
  streamResult.emit("finish", streamFinishEvent);
@@ -556,9 +556,9 @@ async function request(config, fetchOptions, requestCount, timing, _stats, respo
556
556
  const requestOptions = buildHTTPOptions(fetchOptions, isSecure, url);
557
557
  try {
558
558
  const req = httpModule.request(requestOptions, async (res) => {
559
- if (!config.timing.ttfbMs) {
559
+ if (!timing.firstByteTime) {
560
560
  timing.firstByteTime = performance.now();
561
- config.timing.ttfbMs = timing.firstByteTime - timing.startTime;
561
+ config.timing.responseStart = timing.firstByteTime;
562
562
  }
563
563
  const { statusCode, statusMessage, headers, httpVersion, socket } = res;
564
564
  const { remoteAddress, remotePort, localAddress, localPort } = socket;
@@ -588,8 +588,8 @@ async function request(config, fetchOptions, requestCount, timing, _stats, respo
588
588
  contentLength: contentLength ? parseInt(contentLength, 10) : undefined,
589
589
  cookies: cookieArray,
590
590
  timing: {
591
- firstByte: config.timing.ttfbMs,
592
- total: performance.now() - timing.startTime
591
+ firstByte: config.timing.responseStart - config.timing.startTime,
592
+ total: performance.now() - config.timing.startTime
593
593
  }
594
594
  };
595
595
  eventEmitter.emit("headers", headersEvent);
@@ -674,14 +674,7 @@ async function request(config, fetchOptions, requestCount, timing, _stats, respo
674
674
  finalUrl: url.toString(),
675
675
  cookies: config.cookieJar?.cookies() || { array: [], map: {} },
676
676
  urls: [url.toString()],
677
- timing: {
678
- total: config.timing.durationMs || 0,
679
- dns: config.timing.dnsMs,
680
- tcp: config.timing.tcpMs,
681
- tls: config.timing.tlsMs,
682
- firstByte: config.timing.ttfbMs,
683
- download: config.timing.transferMs
684
- },
677
+ timing: getTimingDurations(config),
685
678
  config: sanitizeConfig(config)
686
679
  };
687
680
  streamResult.emit("done", streamFinishEvent);
@@ -738,14 +731,10 @@ async function request(config, fetchOptions, requestCount, timing, _stats, respo
738
731
  fileName: filename,
739
732
  fileSize: contentLengthCounter,
740
733
  timing: {
741
- total: config.timing.durationMs || 0,
742
- dns: config.timing.dnsMs,
743
- tcp: config.timing.tcpMs,
744
- tls: config.timing.tlsMs,
745
- firstByte: config.timing.ttfbMs,
746
- download: config.timing.transferMs || 0
734
+ ...getTimingDurations(config),
735
+ download: getTimingDurations(config).download || 0
747
736
  },
748
- averageSpeed: config.timing.transferMs ? contentLengthCounter / config.timing.transferMs * 1000 : 0,
737
+ averageSpeed: getTimingDurations(config).download ? contentLengthCounter / getTimingDurations(config).download * 1000 : 0,
749
738
  config: sanitizeConfig(config)
750
739
  };
751
740
  downloadResult.emit("finish", finishEvent);
@@ -838,16 +827,16 @@ async function request(config, fetchOptions, requestCount, timing, _stats, respo
838
827
  uploadSize: config.transfer.requestSize || 0,
839
828
  fileName: uploadResult.fileName,
840
829
  timing: {
841
- total: config.timing.durationMs || 0,
842
- dns: config.timing.dnsMs,
843
- tcp: config.timing.tcpMs,
844
- tls: config.timing.tlsMs,
845
- upload: config.timing.ttfbMs || 0,
846
- waiting: config.timing.ttfbMs && config.timing.transferMs ? config.timing.transferMs - config.timing.ttfbMs : 0,
847
- download: config.timing.transferMs
830
+ total: getTimingDurations(config).total,
831
+ dns: getTimingDurations(config).dns,
832
+ tcp: getTimingDurations(config).tcp,
833
+ tls: getTimingDurations(config).tls,
834
+ upload: getTimingDurations(config).firstByte || 0,
835
+ waiting: getTimingDurations(config).download > 0 && getTimingDurations(config).firstByte > 0 ? getTimingDurations(config).download - getTimingDurations(config).firstByte : 0,
836
+ download: getTimingDurations(config).download
848
837
  },
849
- averageUploadSpeed: config.timing.ttfbMs && config.transfer.requestSize ? config.transfer.requestSize / config.timing.ttfbMs * 1000 : 0,
850
- averageDownloadSpeed: config.timing.transferMs ? contentLengthCounter / config.timing.transferMs * 1000 : 0,
838
+ averageUploadSpeed: getTimingDurations(config).firstByte && config.transfer.requestSize ? config.transfer.requestSize / getTimingDurations(config).firstByte * 1000 : 0,
839
+ averageDownloadSpeed: getTimingDurations(config).download ? contentLengthCounter / getTimingDurations(config).download * 1000 : 0,
851
840
  config: sanitizeConfig(config)
852
841
  };
853
842
  uploadResult.emit("finish", uploadFinishEvent);
@@ -886,17 +875,19 @@ async function request(config, fetchOptions, requestCount, timing, _stats, respo
886
875
  socket.unref();
887
876
  }
888
877
  timing.dnsStart = performance.now();
878
+ config.timing.domainLookupStart = timing.dnsStart;
889
879
  socket.on("lookup", () => {
890
- if (!config.timing.dnsMs) {
891
- if (timing.dnsStart)
892
- config.timing.dnsMs = performance.now() - timing.dnsStart;
880
+ if (!timing.dnsEnd) {
881
+ timing.dnsEnd = performance.now();
882
+ config.timing.domainLookupEnd = timing.dnsEnd;
893
883
  timing.tcpStart = performance.now();
884
+ config.timing.connectStart = timing.tcpStart;
894
885
  }
895
886
  });
896
887
  socket.on("secureConnect", () => {
897
- if (!config.timing.tlsMs) {
898
- if (timing.tlsStart && !config.timing.tlsMs)
899
- config.timing.tlsMs = performance.now() - timing.tlsStart;
888
+ if (!timing.tlsEnd && timing.tlsStart) {
889
+ timing.tlsEnd = performance.now();
890
+ config.timing.connectEnd = timing.tlsEnd;
900
891
  }
901
892
  const tls = {
902
893
  cipher: socket.getCipher(),
@@ -920,11 +911,13 @@ async function request(config, fetchOptions, requestCount, timing, _stats, respo
920
911
  };
921
912
  });
922
913
  socket.on("connect", () => {
923
- if (!config.timing.tcpMs) {
924
- if (timing.tcpStart)
925
- config.timing.tcpMs = performance.now() - timing.tcpStart;
926
- if (isSecure)
914
+ if (!timing.tcpEnd) {
915
+ timing.tcpEnd = performance.now();
916
+ config.timing.connectEnd = timing.tcpEnd;
917
+ if (isSecure) {
927
918
  timing.tlsStart = performance.now();
919
+ config.timing.secureConnectionStart = timing.tlsStart;
920
+ }
928
921
  }
929
922
  const { remoteAddress, remotePort, localAddress, localPort, remoteFamily } = socket;
930
923
  if (remoteAddress && !config.network.remoteAddress) {
@@ -995,10 +988,15 @@ async function request(config, fetchOptions, requestCount, timing, _stats, respo
995
988
  });
996
989
  }
997
990
  function updateTiming(config, timing, contentLength, contentLengthCounter, rawHeaders) {
998
- config.timing.endTimestamp = Date.now();
999
- const elapsedMs = performance.now() - timing.startTime;
1000
- config.timing.durationMs = elapsedMs;
1001
- config.timing.transferMs = timing.firstByteTime ? performance.now() - timing.firstByteTime : elapsedMs;
991
+ const now = performance.now();
992
+ config.timing.domainLookupStart = timing.dnsStart || config.timing.startTime;
993
+ config.timing.domainLookupEnd = timing.dnsEnd || timing.dnsStart || config.timing.startTime;
994
+ config.timing.connectStart = timing.tcpStart || timing.dnsEnd || config.timing.startTime;
995
+ config.timing.secureConnectionStart = timing.tlsStart || 0;
996
+ config.timing.connectEnd = timing.tlsEnd || timing.tcpEnd || timing.tcpStart || config.timing.startTime;
997
+ config.timing.requestStart = timing.tlsEnd || timing.tcpEnd || config.timing.startTime;
998
+ config.timing.responseStart = timing.firstByteTime || config.timing.requestStart;
999
+ config.timing.responseEnd = now;
1002
1000
  const bodySize = parseInt(contentLength || "0", 10) || contentLengthCounter;
1003
1001
  config.transfer.bodySize = bodySize;
1004
1002
  let headerSize = 0;
@@ -1031,6 +1029,17 @@ function updateTiming(config, timing, contentLength, contentLengthCounter, rawHe
1031
1029
  };
1032
1030
  }
1033
1031
  }
1032
+ function getTimingDurations(config) {
1033
+ const t = config.timing;
1034
+ return {
1035
+ total: t.responseEnd - t.startTime,
1036
+ dns: t.domainLookupEnd - t.domainLookupStart,
1037
+ tcp: t.secureConnectionStart > 0 ? t.secureConnectionStart - t.connectStart : t.connectEnd - t.connectStart,
1038
+ tls: t.secureConnectionStart > 0 ? t.connectEnd - t.secureConnectionStart : undefined,
1039
+ firstByte: t.responseStart - t.startTime,
1040
+ download: t.responseEnd - t.responseStart
1041
+ };
1042
+ }
1034
1043
  let dnsCache = null;
1035
1044
  function createDNSLookup(cache) {
1036
1045
  return (hostname, optionsOrCallback, callbackOrUndefined) => {
@@ -1168,9 +1177,19 @@ async function setInitialConfig(config, fetchOptions, isSecure, url, httpModule,
1168
1177
  browser: false,
1169
1178
  ssl: isSecure
1170
1179
  };
1171
- const timestampToUse = actualTimestamp || Date.now();
1172
- config.timing = config.timing || { startTimestamp: timestampToUse, endTimestamp: 0, durationMs: 0 };
1173
- config.timing.startTimestamp = config.timing.startTimestamp || timestampToUse;
1180
+ const startTime = performance.now();
1181
+ config.timing = config.timing || {
1182
+ startTime,
1183
+ domainLookupStart: startTime,
1184
+ domainLookupEnd: startTime,
1185
+ connectStart: startTime,
1186
+ secureConnectionStart: 0,
1187
+ connectEnd: startTime,
1188
+ requestStart: startTime,
1189
+ responseStart: startTime,
1190
+ responseEnd: startTime
1191
+ };
1192
+ config.timing.startTime = config.timing.startTime || startTime;
1174
1193
  config.maxRedirectsReached = false;
1175
1194
  config.responseCookies = {
1176
1195
  array: [],
@@ -1188,7 +1207,7 @@ async function setInitialConfig(config, fetchOptions, isSecure, url, httpModule,
1188
1207
  config.requestId = generateRequestId();
1189
1208
  config.sessionId = fetchOptions.sessionId || generateSessionId();
1190
1209
  config.traceId = generateTraceId();
1191
- config.timestamp = config.timing.startTimestamp;
1210
+ config.timestamp = Date.now();
1192
1211
  config.trackingData = {};
1193
1212
  config.transfer = {
1194
1213
  requestSize: 0,