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
@@ -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,
@@ -200,6 +200,30 @@ class Http2SessionPool {
200
200
  this.closeAllSessions();
201
201
  }
202
202
  }
203
+ function updateTiming(config, timing, contentLengthCounter) {
204
+ const now = performance.now();
205
+ config.timing.domainLookupStart = timing.dnsStart || config.timing.startTime;
206
+ config.timing.domainLookupEnd = timing.dnsEnd || timing.dnsStart || config.timing.startTime;
207
+ config.timing.connectStart = timing.tcpStart || timing.dnsEnd || config.timing.startTime;
208
+ config.timing.secureConnectionStart = timing.tlsStart || 0;
209
+ config.timing.connectEnd = timing.tcpEnd || timing.tlsEnd || timing.tcpStart || config.timing.startTime;
210
+ config.timing.requestStart = timing.tcpEnd || config.timing.startTime;
211
+ config.timing.responseStart = timing.firstByteTime || config.timing.requestStart;
212
+ config.timing.responseEnd = now;
213
+ config.transfer.bodySize = contentLengthCounter;
214
+ config.transfer.responseSize = contentLengthCounter;
215
+ }
216
+ function getTimingDurations(config) {
217
+ const t = config.timing;
218
+ return {
219
+ total: t.responseEnd - t.startTime,
220
+ dns: t.domainLookupEnd - t.domainLookupStart,
221
+ tcp: t.secureConnectionStart > 0 ? t.secureConnectionStart - t.connectStart : t.connectEnd - t.connectStart,
222
+ tls: t.secureConnectionStart > 0 ? t.connectEnd - t.secureConnectionStart : undefined,
223
+ firstByte: t.responseStart - t.startTime,
224
+ download: t.responseEnd - t.responseStart
225
+ };
226
+ }
203
227
  const responseCacheInstances = new Map;
204
228
  function getCacheConfigKey(option) {
205
229
  if (option === true)
@@ -489,10 +513,11 @@ async function executeHttp2Request(fetchOptions, config, options, perform, fs, s
489
513
  const maxRetries = config?.retry?.maxRetries || 0;
490
514
  const incrementDelay = config?.retry?.incrementDelay || false;
491
515
  const statusCodes = config?.retry?.statusCodes;
516
+ const startTime = performance.now();
492
517
  const timing = {
493
- startTime: performance.now(),
494
- startTimestamp: Date.now()
518
+ startTime
495
519
  };
520
+ config.timing.startTime = startTime;
496
521
  const ABSOLUTE_MAX_ATTEMPTS = 50;
497
522
  const visitedUrls = new Set;
498
523
  let totalAttempts = 0;
@@ -662,7 +687,6 @@ async function executeHttp2Stream(config, fetchOptions, requestCount, timing, _s
662
687
  config.isSecure = isSecure;
663
688
  config.finalUrl = url.href;
664
689
  config.network.protocol = "h2";
665
- config.timing.startTimestamp = timing.startTimestamp;
666
690
  }
667
691
  const headers = {
668
692
  [http2.constants.HTTP2_HEADER_METHOD]: fetchOptions.method.toUpperCase(),
@@ -739,9 +763,9 @@ async function executeHttp2Stream(config, fetchOptions, requestCount, timing, _s
739
763
  responseHeaders = headers;
740
764
  status = Number(headers[http2.constants.HTTP2_HEADER_STATUS]) || 200;
741
765
  statusText = getStatusText(status);
742
- if (!config.timing.ttfbMs) {
766
+ if (!timing.firstByteTime) {
743
767
  timing.firstByteTime = performance.now();
744
- config.timing.ttfbMs = timing.firstByteTime - timing.startTime;
768
+ config.timing.responseStart = timing.firstByteTime;
745
769
  }
746
770
  const location = headers["location"];
747
771
  const isRedirect = status >= 300 && status < 400 && location;
@@ -760,8 +784,8 @@ async function executeHttp2Stream(config, fetchOptions, requestCount, timing, _s
760
784
  contentLength: headers["content-length"] ? parseInt(headers["content-length"], 10) : undefined,
761
785
  cookies: config.responseCookies?.array || [],
762
786
  timing: {
763
- firstByte: config.timing.ttfbMs,
764
- total: performance.now() - timing.startTime
787
+ firstByte: config.timing.responseStart - config.timing.startTime,
788
+ total: performance.now() - config.timing.startTime
765
789
  }
766
790
  };
767
791
  eventEmitter.emit("headers", headersEvent);
@@ -798,9 +822,7 @@ async function executeHttp2Stream(config, fetchOptions, requestCount, timing, _s
798
822
  }
799
823
  });
800
824
  req.on("end", async () => {
801
- config.timing.endTimestamp = Date.now();
802
- config.timing.durationMs = performance.now() - timing.startTime;
803
- config.timing.transferMs = timing.firstByteTime ? performance.now() - timing.firstByteTime : config.timing.durationMs;
825
+ updateTiming(config, timing, contentLengthCounter);
804
826
  if (!config.transfer) {
805
827
  config.transfer = { requestSize: 0, responseSize: 0, headerSize: 0, bodySize: 0 };
806
828
  }
@@ -820,8 +842,6 @@ async function executeHttp2Stream(config, fetchOptions, requestCount, timing, _s
820
842
  config.transfer.requestSize = Buffer.byteLength(JSON.stringify(body), "utf8");
821
843
  }
822
844
  }
823
- config.transfer.bodySize = contentLengthCounter;
824
- config.transfer.responseSize = contentLengthCounter;
825
845
  (sessionPool || Http2SessionPool.getInstance()).releaseSession(url);
826
846
  if (_stats.statusOnNext === "redirect") {
827
847
  const partialResponse = {
@@ -920,14 +940,10 @@ async function executeHttp2Stream(config, fetchOptions, requestCount, timing, _s
920
940
  fileName: config.fileName,
921
941
  fileSize: responseBody.length,
922
942
  timing: {
923
- total: config.timing.durationMs || 0,
924
- dns: config.timing.dnsMs,
925
- tcp: config.timing.tcpMs,
926
- tls: config.timing.tlsMs,
927
- firstByte: config.timing.ttfbMs,
928
- download: config.timing.transferMs || 0
943
+ ...getTimingDurations(config),
944
+ download: getTimingDurations(config).download || 0
929
945
  },
930
- averageSpeed: config.timing.transferMs ? responseBody.length / config.timing.transferMs * 1000 : 0,
946
+ averageSpeed: getTimingDurations(config).download ? responseBody.length / getTimingDurations(config).download * 1000 : 0,
931
947
  config: sanitizeConfig(config)
932
948
  };
933
949
  downloadResult.emit("finish", downloadFinishEvent);
@@ -962,14 +978,7 @@ async function executeHttp2Stream(config, fetchOptions, requestCount, timing, _s
962
978
  finalUrl: url.href,
963
979
  cookies: config.responseCookies || { array: [], serialized: [], netscape: "", string: "", setCookiesString: [] },
964
980
  urls: buildUrlTree(config, url.href),
965
- timing: {
966
- total: config.timing.durationMs || 0,
967
- dns: config.timing.dnsMs,
968
- tcp: config.timing.tcpMs,
969
- tls: config.timing.tlsMs,
970
- firstByte: config.timing.ttfbMs,
971
- download: config.timing.transferMs
972
- },
981
+ timing: getTimingDurations(config),
973
982
  config: sanitizeConfig(config)
974
983
  };
975
984
  streamResult.emit("finish", streamFinishEvent);
@@ -992,16 +1001,12 @@ async function executeHttp2Stream(config, fetchOptions, requestCount, timing, _s
992
1001
  urls: buildUrlTree(config, url.href),
993
1002
  uploadSize: config.transfer.requestSize || 0,
994
1003
  timing: {
995
- total: config.timing.durationMs || 0,
996
- dns: config.timing.dnsMs,
997
- tcp: config.timing.tcpMs,
998
- tls: config.timing.tlsMs,
999
- upload: config.timing.transferMs || 0,
1000
- waiting: config.timing.ttfbMs || 0,
1001
- download: config.timing.transferMs
1004
+ ...getTimingDurations(config),
1005
+ upload: getTimingDurations(config).firstByte || 0,
1006
+ waiting: getTimingDurations(config).download > 0 && getTimingDurations(config).firstByte > 0 ? getTimingDurations(config).download - getTimingDurations(config).firstByte : 0
1002
1007
  },
1003
- averageUploadSpeed: config.timing.transferMs ? (config.transfer.requestSize || 0) / config.timing.transferMs * 1000 : 0,
1004
- averageDownloadSpeed: config.timing.transferMs ? contentLengthCounter / config.timing.transferMs * 1000 : 0,
1008
+ averageUploadSpeed: getTimingDurations(config).firstByte && config.transfer.requestSize ? config.transfer.requestSize / getTimingDurations(config).firstByte * 1000 : 0,
1009
+ averageDownloadSpeed: getTimingDurations(config).download ? contentLengthCounter / getTimingDurations(config).download * 1000 : 0,
1005
1010
  config: sanitizeConfig(config)
1006
1011
  };
1007
1012
  uploadResult.emit("finish", uploadFinishEvent);
@@ -200,6 +200,30 @@ class Http2SessionPool {
200
200
  this.closeAllSessions();
201
201
  }
202
202
  }
203
+ function updateTiming(config, timing, contentLengthCounter) {
204
+ const now = performance.now();
205
+ config.timing.domainLookupStart = timing.dnsStart || config.timing.startTime;
206
+ config.timing.domainLookupEnd = timing.dnsEnd || timing.dnsStart || config.timing.startTime;
207
+ config.timing.connectStart = timing.tcpStart || timing.dnsEnd || config.timing.startTime;
208
+ config.timing.secureConnectionStart = timing.tlsStart || 0;
209
+ config.timing.connectEnd = timing.tcpEnd || timing.tlsEnd || timing.tcpStart || config.timing.startTime;
210
+ config.timing.requestStart = timing.tcpEnd || config.timing.startTime;
211
+ config.timing.responseStart = timing.firstByteTime || config.timing.requestStart;
212
+ config.timing.responseEnd = now;
213
+ config.transfer.bodySize = contentLengthCounter;
214
+ config.transfer.responseSize = contentLengthCounter;
215
+ }
216
+ function getTimingDurations(config) {
217
+ const t = config.timing;
218
+ return {
219
+ total: t.responseEnd - t.startTime,
220
+ dns: t.domainLookupEnd - t.domainLookupStart,
221
+ tcp: t.secureConnectionStart > 0 ? t.secureConnectionStart - t.connectStart : t.connectEnd - t.connectStart,
222
+ tls: t.secureConnectionStart > 0 ? t.connectEnd - t.secureConnectionStart : undefined,
223
+ firstByte: t.responseStart - t.startTime,
224
+ download: t.responseEnd - t.responseStart
225
+ };
226
+ }
203
227
  const responseCacheInstances = new Map;
204
228
  function getCacheConfigKey(option) {
205
229
  if (option === true)
@@ -489,10 +513,11 @@ async function executeHttp2Request(fetchOptions, config, options, perform, fs, s
489
513
  const maxRetries = config?.retry?.maxRetries || 0;
490
514
  const incrementDelay = config?.retry?.incrementDelay || false;
491
515
  const statusCodes = config?.retry?.statusCodes;
516
+ const startTime = performance.now();
492
517
  const timing = {
493
- startTime: performance.now(),
494
- startTimestamp: Date.now()
518
+ startTime
495
519
  };
520
+ config.timing.startTime = startTime;
496
521
  const ABSOLUTE_MAX_ATTEMPTS = 50;
497
522
  const visitedUrls = new Set;
498
523
  let totalAttempts = 0;
@@ -662,7 +687,6 @@ async function executeHttp2Stream(config, fetchOptions, requestCount, timing, _s
662
687
  config.isSecure = isSecure;
663
688
  config.finalUrl = url.href;
664
689
  config.network.protocol = "h2";
665
- config.timing.startTimestamp = timing.startTimestamp;
666
690
  }
667
691
  const headers = {
668
692
  [http2.constants.HTTP2_HEADER_METHOD]: fetchOptions.method.toUpperCase(),
@@ -739,9 +763,9 @@ async function executeHttp2Stream(config, fetchOptions, requestCount, timing, _s
739
763
  responseHeaders = headers;
740
764
  status = Number(headers[http2.constants.HTTP2_HEADER_STATUS]) || 200;
741
765
  statusText = getStatusText(status);
742
- if (!config.timing.ttfbMs) {
766
+ if (!timing.firstByteTime) {
743
767
  timing.firstByteTime = performance.now();
744
- config.timing.ttfbMs = timing.firstByteTime - timing.startTime;
768
+ config.timing.responseStart = timing.firstByteTime;
745
769
  }
746
770
  const location = headers["location"];
747
771
  const isRedirect = status >= 300 && status < 400 && location;
@@ -760,8 +784,8 @@ async function executeHttp2Stream(config, fetchOptions, requestCount, timing, _s
760
784
  contentLength: headers["content-length"] ? parseInt(headers["content-length"], 10) : undefined,
761
785
  cookies: config.responseCookies?.array || [],
762
786
  timing: {
763
- firstByte: config.timing.ttfbMs,
764
- total: performance.now() - timing.startTime
787
+ firstByte: config.timing.responseStart - config.timing.startTime,
788
+ total: performance.now() - config.timing.startTime
765
789
  }
766
790
  };
767
791
  eventEmitter.emit("headers", headersEvent);
@@ -798,9 +822,7 @@ async function executeHttp2Stream(config, fetchOptions, requestCount, timing, _s
798
822
  }
799
823
  });
800
824
  req.on("end", async () => {
801
- config.timing.endTimestamp = Date.now();
802
- config.timing.durationMs = performance.now() - timing.startTime;
803
- config.timing.transferMs = timing.firstByteTime ? performance.now() - timing.firstByteTime : config.timing.durationMs;
825
+ updateTiming(config, timing, contentLengthCounter);
804
826
  if (!config.transfer) {
805
827
  config.transfer = { requestSize: 0, responseSize: 0, headerSize: 0, bodySize: 0 };
806
828
  }
@@ -820,8 +842,6 @@ async function executeHttp2Stream(config, fetchOptions, requestCount, timing, _s
820
842
  config.transfer.requestSize = Buffer.byteLength(JSON.stringify(body), "utf8");
821
843
  }
822
844
  }
823
- config.transfer.bodySize = contentLengthCounter;
824
- config.transfer.responseSize = contentLengthCounter;
825
845
  (sessionPool || Http2SessionPool.getInstance()).releaseSession(url);
826
846
  if (_stats.statusOnNext === "redirect") {
827
847
  const partialResponse = {
@@ -920,14 +940,10 @@ async function executeHttp2Stream(config, fetchOptions, requestCount, timing, _s
920
940
  fileName: config.fileName,
921
941
  fileSize: responseBody.length,
922
942
  timing: {
923
- total: config.timing.durationMs || 0,
924
- dns: config.timing.dnsMs,
925
- tcp: config.timing.tcpMs,
926
- tls: config.timing.tlsMs,
927
- firstByte: config.timing.ttfbMs,
928
- download: config.timing.transferMs || 0
943
+ ...getTimingDurations(config),
944
+ download: getTimingDurations(config).download || 0
929
945
  },
930
- averageSpeed: config.timing.transferMs ? responseBody.length / config.timing.transferMs * 1000 : 0,
946
+ averageSpeed: getTimingDurations(config).download ? responseBody.length / getTimingDurations(config).download * 1000 : 0,
931
947
  config: sanitizeConfig(config)
932
948
  };
933
949
  downloadResult.emit("finish", downloadFinishEvent);
@@ -962,14 +978,7 @@ async function executeHttp2Stream(config, fetchOptions, requestCount, timing, _s
962
978
  finalUrl: url.href,
963
979
  cookies: config.responseCookies || { array: [], serialized: [], netscape: "", string: "", setCookiesString: [] },
964
980
  urls: buildUrlTree(config, url.href),
965
- timing: {
966
- total: config.timing.durationMs || 0,
967
- dns: config.timing.dnsMs,
968
- tcp: config.timing.tcpMs,
969
- tls: config.timing.tlsMs,
970
- firstByte: config.timing.ttfbMs,
971
- download: config.timing.transferMs
972
- },
981
+ timing: getTimingDurations(config),
973
982
  config: sanitizeConfig(config)
974
983
  };
975
984
  streamResult.emit("finish", streamFinishEvent);
@@ -992,16 +1001,12 @@ async function executeHttp2Stream(config, fetchOptions, requestCount, timing, _s
992
1001
  urls: buildUrlTree(config, url.href),
993
1002
  uploadSize: config.transfer.requestSize || 0,
994
1003
  timing: {
995
- total: config.timing.durationMs || 0,
996
- dns: config.timing.dnsMs,
997
- tcp: config.timing.tcpMs,
998
- tls: config.timing.tlsMs,
999
- upload: config.timing.transferMs || 0,
1000
- waiting: config.timing.ttfbMs || 0,
1001
- download: config.timing.transferMs
1004
+ ...getTimingDurations(config),
1005
+ upload: getTimingDurations(config).firstByte || 0,
1006
+ waiting: getTimingDurations(config).download > 0 && getTimingDurations(config).firstByte > 0 ? getTimingDurations(config).download - getTimingDurations(config).firstByte : 0
1002
1007
  },
1003
- averageUploadSpeed: config.timing.transferMs ? (config.transfer.requestSize || 0) / config.timing.transferMs * 1000 : 0,
1004
- averageDownloadSpeed: config.timing.transferMs ? contentLengthCounter / config.timing.transferMs * 1000 : 0,
1008
+ averageUploadSpeed: getTimingDurations(config).firstByte && config.transfer.requestSize ? config.transfer.requestSize / getTimingDurations(config).firstByte * 1000 : 0,
1009
+ averageDownloadSpeed: getTimingDurations(config).download ? contentLengthCounter / getTimingDurations(config).download * 1000 : 0,
1005
1010
  config: sanitizeConfig(config)
1006
1011
  };
1007
1012
  uploadResult.emit("finish", uploadFinishEvent);
@@ -1,6 +1,6 @@
1
- const _mod_i8j93l = require('./picker.cjs');
2
- exports.detectRuntime = _mod_i8j93l.detectRuntime;
3
- exports.getAdapterCapabilities = _mod_i8j93l.getAdapterCapabilities;
4
- exports.buildAdapterContext = _mod_i8j93l.buildAdapterContext;
5
- exports.getAvailableAdapters = _mod_i8j93l.getAvailableAdapters;
6
- exports.selectAdapter = _mod_i8j93l.selectAdapter;;
1
+ const _mod_cotolp = require('./picker.cjs');
2
+ exports.detectRuntime = _mod_cotolp.detectRuntime;
3
+ exports.getAdapterCapabilities = _mod_cotolp.getAdapterCapabilities;
4
+ exports.buildAdapterContext = _mod_cotolp.buildAdapterContext;
5
+ exports.getAvailableAdapters = _mod_cotolp.getAvailableAdapters;
6
+ exports.selectAdapter = _mod_cotolp.selectAdapter;;
@@ -17,6 +17,30 @@ const Environment = {
17
17
  hasFormData: typeof FormData !== "undefined",
18
18
  hasAbortController: typeof AbortController !== "undefined"
19
19
  };
20
+ function updateTiming(config, timing, bodySize) {
21
+ const now = performance.now();
22
+ config.timing.domainLookupStart = config.timing.startTime;
23
+ config.timing.domainLookupEnd = config.timing.startTime;
24
+ config.timing.connectStart = config.timing.startTime;
25
+ config.timing.secureConnectionStart = 0;
26
+ config.timing.connectEnd = config.timing.startTime;
27
+ config.timing.requestStart = config.timing.startTime;
28
+ config.timing.responseStart = timing.firstByteTime || config.timing.startTime;
29
+ config.timing.responseEnd = now;
30
+ config.transfer.bodySize = bodySize;
31
+ config.transfer.responseSize = bodySize;
32
+ }
33
+ function getTimingDurations(config) {
34
+ const t = config.timing;
35
+ return {
36
+ total: t.responseEnd - t.startTime,
37
+ dns: t.domainLookupEnd - t.domainLookupStart,
38
+ tcp: t.secureConnectionStart > 0 ? t.secureConnectionStart - t.connectStart : t.connectEnd - t.connectStart,
39
+ tls: t.secureConnectionStart > 0 ? t.connectEnd - t.secureConnectionStart : undefined,
40
+ firstByte: t.responseStart - t.startTime,
41
+ download: t.responseEnd - t.responseStart
42
+ };
43
+ }
20
44
  const responseCacheInstances = new Map;
21
45
  function getCacheConfigKey(option) {
22
46
  if (option === true)
@@ -227,10 +251,11 @@ async function executeFetchRequest(fetchOptions, config, options, perform, strea
227
251
  const maxRetries = config?.retry?.maxRetries || 0;
228
252
  const incrementDelay = config?.retry?.incrementDelay || false;
229
253
  const statusCodes = config?.retry?.statusCodes;
254
+ const startTime = performance.now();
230
255
  const timing = {
231
- startTime: performance.now(),
232
- startTimestamp: Date.now()
256
+ startTime
233
257
  };
258
+ config.timing.startTime = startTime;
234
259
  const ABSOLUTE_MAX_ATTEMPTS = 50;
235
260
  let totalAttempts = 0;
236
261
  config.setSignal();
@@ -294,7 +319,6 @@ async function executeSingleRequest(config, fetchOptions, timing, streamResult,
294
319
  config.isSecure = isSecure;
295
320
  config.finalUrl = url;
296
321
  config.network.protocol = isSecure ? "https" : "http";
297
- config.timing.startTimestamp = timing.startTimestamp;
298
322
  const reqHeaders = fetchOptions.headers instanceof RezoHeaders ? fetchOptions.headers.toObject() : fetchOptions.headers || {};
299
323
  const headers = toFetchHeaders(reqHeaders);
300
324
  const eventEmitter = streamResult || downloadResult || uploadResult;
@@ -347,9 +371,9 @@ async function executeSingleRequest(config, fetchOptions, timing, streamResult,
347
371
  if (timeoutId)
348
372
  clearTimeout(timeoutId);
349
373
  }
350
- if (!config.timing.ttfbMs) {
374
+ if (!timing.firstByteTime) {
351
375
  timing.firstByteTime = performance.now();
352
- config.timing.ttfbMs = timing.firstByteTime - timing.startTime;
376
+ config.timing.responseStart = timing.firstByteTime;
353
377
  }
354
378
  const status = response.status;
355
379
  const statusText = response.statusText;
@@ -373,8 +397,8 @@ async function executeSingleRequest(config, fetchOptions, timing, streamResult,
373
397
  contentLength: contentLength ? parseInt(contentLength, 10) : undefined,
374
398
  cookies: cookies.array,
375
399
  timing: {
376
- firstByte: config.timing.ttfbMs,
377
- total: performance.now() - timing.startTime
400
+ firstByte: config.timing.responseStart - config.timing.startTime,
401
+ total: performance.now() - config.timing.startTime
378
402
  }
379
403
  };
380
404
  eventEmitter.emit("headers", headersEvent);
@@ -428,11 +452,7 @@ async function executeSingleRequest(config, fetchOptions, timing, streamResult,
428
452
  bodySize = text.length;
429
453
  }
430
454
  }
431
- config.timing.endTimestamp = Date.now();
432
- config.timing.durationMs = performance.now() - timing.startTime;
433
- config.timing.transferMs = timing.firstByteTime ? performance.now() - timing.firstByteTime : config.timing.durationMs;
434
- config.transfer.bodySize = bodySize;
435
- config.transfer.responseSize = bodySize;
455
+ updateTiming(config, timing, bodySize);
436
456
  if (status >= 400) {
437
457
  const error = builErrorFromResponse(`HTTP Error ${status}: ${statusText}`, {
438
458
  status,
@@ -466,11 +486,7 @@ async function executeSingleRequest(config, fetchOptions, timing, streamResult,
466
486
  finalUrl: url,
467
487
  cookies,
468
488
  urls: buildUrlTree(config, url),
469
- timing: {
470
- total: config.timing.durationMs || 0,
471
- firstByte: config.timing.ttfbMs,
472
- download: config.timing.transferMs
473
- },
489
+ timing: getTimingDurations(config),
474
490
  config: sanitizeConfig(config)
475
491
  };
476
492
  streamResult.emit("finish", streamFinishEvent);
@@ -491,11 +507,10 @@ async function executeSingleRequest(config, fetchOptions, timing, streamResult,
491
507
  fileName: config.fileName || "",
492
508
  fileSize: bodySize,
493
509
  timing: {
494
- total: config.timing.durationMs || 0,
495
- firstByte: config.timing.ttfbMs,
496
- download: config.timing.transferMs || 0
510
+ ...getTimingDurations(config),
511
+ download: getTimingDurations(config).download || 0
497
512
  },
498
- averageSpeed: config.timing.transferMs ? bodySize / config.timing.transferMs * 1000 : 0,
513
+ averageSpeed: getTimingDurations(config).download ? bodySize / getTimingDurations(config).download * 1000 : 0,
499
514
  config: sanitizeConfig(config)
500
515
  };
501
516
  downloadResult.emit("finish", downloadFinishEvent);
@@ -517,13 +532,12 @@ async function executeSingleRequest(config, fetchOptions, timing, streamResult,
517
532
  urls: buildUrlTree(config, url),
518
533
  uploadSize: config.transfer.requestSize || 0,
519
534
  timing: {
520
- total: config.timing.durationMs || 0,
521
- upload: config.timing.transferMs || 0,
522
- waiting: config.timing.ttfbMs || 0,
523
- download: config.timing.transferMs
535
+ ...getTimingDurations(config),
536
+ upload: getTimingDurations(config).firstByte || 0,
537
+ waiting: getTimingDurations(config).download > 0 && getTimingDurations(config).firstByte > 0 ? getTimingDurations(config).download - getTimingDurations(config).firstByte : 0
524
538
  },
525
- averageUploadSpeed: config.timing.transferMs ? (config.transfer.requestSize || 0) / config.timing.transferMs * 1000 : 0,
526
- averageDownloadSpeed: config.timing.transferMs ? bodySize / config.timing.transferMs * 1000 : 0,
539
+ averageUploadSpeed: getTimingDurations(config).firstByte && config.transfer.requestSize ? config.transfer.requestSize / getTimingDurations(config).firstByte * 1000 : 0,
540
+ averageDownloadSpeed: getTimingDurations(config).download ? bodySize / getTimingDurations(config).download * 1000 : 0,
527
541
  config: sanitizeConfig(config)
528
542
  };
529
543
  uploadResult.emit("finish", uploadFinishEvent);