rezo 1.0.11 → 1.0.13

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 +73 -10
  2. package/dist/adapters/curl.js +73 -10
  3. package/dist/adapters/entries/curl.d.ts +66 -1
  4. package/dist/adapters/entries/fetch.d.ts +66 -1
  5. package/dist/adapters/entries/http.d.ts +66 -1
  6. package/dist/adapters/entries/http2.d.ts +66 -1
  7. package/dist/adapters/entries/react-native.d.ts +66 -1
  8. package/dist/adapters/entries/xhr.d.ts +66 -1
  9. package/dist/adapters/fetch.cjs +106 -59
  10. package/dist/adapters/fetch.js +106 -59
  11. package/dist/adapters/http.cjs +28 -15
  12. package/dist/adapters/http.js +28 -15
  13. package/dist/adapters/http2.cjs +114 -55
  14. package/dist/adapters/http2.js +114 -55
  15. package/dist/adapters/index.cjs +6 -6
  16. package/dist/cache/index.cjs +13 -13
  17. package/dist/crawler.d.ts +66 -1
  18. package/dist/entries/crawler.cjs +5 -5
  19. package/dist/index.cjs +24 -24
  20. package/dist/index.d.ts +66 -1
  21. package/dist/platform/browser.d.ts +66 -1
  22. package/dist/platform/bun.d.ts +66 -1
  23. package/dist/platform/deno.d.ts +66 -1
  24. package/dist/platform/node.d.ts +66 -1
  25. package/dist/platform/react-native.d.ts +66 -1
  26. package/dist/platform/worker.d.ts +66 -1
  27. package/dist/plugin/index.cjs +36 -36
  28. package/dist/proxy/index.cjs +2 -2
  29. package/dist/queue/index.cjs +8 -8
  30. package/dist/responses/buildError.cjs +5 -1
  31. package/dist/responses/buildError.js +5 -1
  32. package/dist/responses/buildResponse.cjs +30 -3
  33. package/dist/responses/buildResponse.js +30 -3
  34. package/dist/utils/compression.cjs +6 -6
  35. package/dist/utils/compression.js +6 -6
  36. package/dist/utils/headers.cjs +17 -0
  37. package/dist/utils/headers.js +17 -1
  38. package/dist/utils/http-config.cjs +47 -5
  39. package/dist/utils/http-config.js +47 -5
  40. package/package.json +1 -1
@@ -767,6 +767,9 @@ async function request(config, fetchOptions, requestCount, timing, _stats, respo
767
767
  }
768
768
  });
769
769
  req.on("socket", (socket) => {
770
+ if (socket && typeof socket.unref === "function") {
771
+ socket.unref();
772
+ }
770
773
  timing.dnsStart = performance.now();
771
774
  socket.on("lookup", () => {
772
775
  if (!config.timing.dnsMs) {
@@ -818,10 +821,23 @@ async function request(config, fetchOptions, requestCount, timing, _stats, respo
818
821
  }
819
822
  });
820
823
  });
824
+ req.on("error", (error) => {
825
+ _stats.statusOnNext = "error";
826
+ updateTiming(config, timing, "", 0);
827
+ const e = buildSmartError(config, fetchOptions, error);
828
+ const eventEmitter = streamResult || downloadResult || uploadResult;
829
+ if (eventEmitter) {
830
+ eventEmitter.emit("error", e);
831
+ }
832
+ resolve(e);
833
+ return;
834
+ });
835
+ let bodyPiped = false;
821
836
  if (body) {
822
837
  if (body instanceof URLSearchParams || body instanceof RezoURLSearchParams) {
823
838
  req.write(body.toString());
824
839
  } else if (body instanceof FormData || body instanceof RezoFormData) {
840
+ bodyPiped = true;
825
841
  if (body instanceof RezoFormData) {
826
842
  req.setHeader("Content-Type", `multipart/form-data; boundary=${body.getBoundary()}`);
827
843
  body.pipe(req);
@@ -830,24 +846,18 @@ async function request(config, fetchOptions, requestCount, timing, _stats, respo
830
846
  req.setHeader("Content-Type", `multipart/form-data; boundary=${form.getBoundary()}`);
831
847
  form.pipe(req);
832
848
  }
833
- } else if (typeof body === "object" && !(body instanceof Buffer) && !(body instanceof Uint8Array) && !(body instanceof Readable)) {
849
+ } else if (body instanceof Readable) {
850
+ bodyPiped = true;
851
+ body.pipe(req);
852
+ } else if (typeof body === "object" && !(body instanceof Buffer) && !(body instanceof Uint8Array)) {
834
853
  req.write(JSON.stringify(body));
835
854
  } else {
836
855
  req.write(body);
837
856
  }
838
857
  }
839
- req.end();
840
- req.on("error", (error) => {
841
- _stats.statusOnNext = "error";
842
- updateTiming(config, timing, "", 0);
843
- const e = buildSmartError(config, fetchOptions, error);
844
- const eventEmitter = streamResult || downloadResult || uploadResult;
845
- if (eventEmitter) {
846
- eventEmitter.emit("error", e);
847
- }
848
- resolve(e);
849
- return;
850
- });
858
+ if (!bodyPiped) {
859
+ req.end();
860
+ }
851
861
  } catch (error) {
852
862
  _stats.statusOnNext = "error";
853
863
  updateTiming(config, timing, "", 0);
@@ -944,13 +954,16 @@ function buildHTTPOptions(fetchOptions, isSecure, url) {
944
954
  rejectUnauthorized,
945
955
  useSecureContext = true,
946
956
  auth,
947
- dnsCache: dnsCacheOption
957
+ dnsCache: dnsCacheOption,
958
+ keepAlive = false,
959
+ keepAliveMsecs = 60000
948
960
  } = fetchOptions;
949
961
  const secureContext = isSecure && useSecureContext ? new https.Agent({
950
962
  secureContext: createSecureContext(),
951
963
  servername: url.host,
952
964
  rejectUnauthorized,
953
- keepAlive: true
965
+ keepAlive,
966
+ keepAliveMsecs: keepAlive ? keepAliveMsecs : undefined
954
967
  }) : undefined;
955
968
  const customAgent = url.protocol === "https:" && httpsAgent ? httpsAgent : httpAgent ? httpAgent : undefined;
956
969
  const agent = parseProxy(proxy) || customAgent || secureContext;
@@ -767,6 +767,9 @@ async function request(config, fetchOptions, requestCount, timing, _stats, respo
767
767
  }
768
768
  });
769
769
  req.on("socket", (socket) => {
770
+ if (socket && typeof socket.unref === "function") {
771
+ socket.unref();
772
+ }
770
773
  timing.dnsStart = performance.now();
771
774
  socket.on("lookup", () => {
772
775
  if (!config.timing.dnsMs) {
@@ -818,10 +821,23 @@ async function request(config, fetchOptions, requestCount, timing, _stats, respo
818
821
  }
819
822
  });
820
823
  });
824
+ req.on("error", (error) => {
825
+ _stats.statusOnNext = "error";
826
+ updateTiming(config, timing, "", 0);
827
+ const e = buildSmartError(config, fetchOptions, error);
828
+ const eventEmitter = streamResult || downloadResult || uploadResult;
829
+ if (eventEmitter) {
830
+ eventEmitter.emit("error", e);
831
+ }
832
+ resolve(e);
833
+ return;
834
+ });
835
+ let bodyPiped = false;
821
836
  if (body) {
822
837
  if (body instanceof URLSearchParams || body instanceof RezoURLSearchParams) {
823
838
  req.write(body.toString());
824
839
  } else if (body instanceof FormData || body instanceof RezoFormData) {
840
+ bodyPiped = true;
825
841
  if (body instanceof RezoFormData) {
826
842
  req.setHeader("Content-Type", `multipart/form-data; boundary=${body.getBoundary()}`);
827
843
  body.pipe(req);
@@ -830,24 +846,18 @@ async function request(config, fetchOptions, requestCount, timing, _stats, respo
830
846
  req.setHeader("Content-Type", `multipart/form-data; boundary=${form.getBoundary()}`);
831
847
  form.pipe(req);
832
848
  }
833
- } else if (typeof body === "object" && !(body instanceof Buffer) && !(body instanceof Uint8Array) && !(body instanceof Readable)) {
849
+ } else if (body instanceof Readable) {
850
+ bodyPiped = true;
851
+ body.pipe(req);
852
+ } else if (typeof body === "object" && !(body instanceof Buffer) && !(body instanceof Uint8Array)) {
834
853
  req.write(JSON.stringify(body));
835
854
  } else {
836
855
  req.write(body);
837
856
  }
838
857
  }
839
- req.end();
840
- req.on("error", (error) => {
841
- _stats.statusOnNext = "error";
842
- updateTiming(config, timing, "", 0);
843
- const e = buildSmartError(config, fetchOptions, error);
844
- const eventEmitter = streamResult || downloadResult || uploadResult;
845
- if (eventEmitter) {
846
- eventEmitter.emit("error", e);
847
- }
848
- resolve(e);
849
- return;
850
- });
858
+ if (!bodyPiped) {
859
+ req.end();
860
+ }
851
861
  } catch (error) {
852
862
  _stats.statusOnNext = "error";
853
863
  updateTiming(config, timing, "", 0);
@@ -944,13 +954,16 @@ function buildHTTPOptions(fetchOptions, isSecure, url) {
944
954
  rejectUnauthorized,
945
955
  useSecureContext = true,
946
956
  auth,
947
- dnsCache: dnsCacheOption
957
+ dnsCache: dnsCacheOption,
958
+ keepAlive = false,
959
+ keepAliveMsecs = 60000
948
960
  } = fetchOptions;
949
961
  const secureContext = isSecure && useSecureContext ? new https.Agent({
950
962
  secureContext: createSecureContext(),
951
963
  servername: url.host,
952
964
  rejectUnauthorized,
953
- keepAlive: true
965
+ keepAlive,
966
+ keepAliveMsecs: keepAlive ? keepAliveMsecs : undefined
954
967
  }) : undefined;
955
968
  const customAgent = url.protocol === "https:" && httpsAgent ? httpsAgent : httpAgent ? httpAgent : undefined;
956
969
  const agent = parseProxy(proxy) || customAgent || secureContext;
@@ -4,14 +4,15 @@ const { URL } = require("node:url");
4
4
  const { Readable } = require("node:stream");
5
5
  const { RezoError } = require('../errors/rezo-error.cjs');
6
6
  const { buildSmartError, buildDecompressionError, builErrorFromResponse, buildDownloadError } = require('../responses/buildError.cjs');
7
- const { Cookie } = require('../utils/cookies.cjs');
7
+ const { RezoCookieJar } = require('../utils/cookies.cjs');
8
8
  const RezoFormData = require('../utils/form-data.cjs');
9
9
  const { getDefaultConfig, prepareHTTPOptions } = require('../utils/http-config.cjs');
10
- const { RezoHeaders } = require('../utils/headers.cjs');
10
+ const { RezoHeaders, sanitizeHttp2Headers } = require('../utils/headers.cjs');
11
11
  const { RezoURLSearchParams } = require('../utils/data-operations.cjs');
12
12
  const { StreamResponse } = require('../responses/stream.cjs');
13
13
  const { DownloadResponse } = require('../responses/download.cjs');
14
14
  const { UploadResponse } = require('../responses/upload.cjs');
15
+ const { CompressionUtil } = require('../utils/compression.cjs');
15
16
  const { isSameDomain, RezoPerformance } = require('../utils/tools.cjs');
16
17
  const { ResponseCache } = require('../cache/response-cache.cjs');
17
18
  let zstdDecompressSync = null;
@@ -142,6 +143,9 @@ class Http2SessionPool {
142
143
  reject(new Error(`HTTP/2 connection timeout after ${timeout}ms`));
143
144
  }
144
145
  }, timeout) : null;
146
+ if (timeoutId && typeof timeoutId === "object" && "unref" in timeoutId) {
147
+ timeoutId.unref();
148
+ }
145
149
  session.on("connect", () => {
146
150
  if (!settled) {
147
151
  settled = true;
@@ -166,6 +170,12 @@ class Http2SessionPool {
166
170
  if (entry) {
167
171
  entry.refCount = Math.max(0, entry.refCount - 1);
168
172
  entry.lastUsed = Date.now();
173
+ if (entry.refCount === 0) {
174
+ const socket = entry.session.socket;
175
+ if (socket && typeof socket.unref === "function") {
176
+ socket.unref();
177
+ }
178
+ }
169
179
  }
170
180
  }
171
181
  closeSession(url) {
@@ -271,38 +281,66 @@ function updateCookies(config, headers, url) {
271
281
  if (!setCookieHeaders)
272
282
  return;
273
283
  const cookieHeaderArray = Array.isArray(setCookieHeaders) ? setCookieHeaders : [setCookieHeaders];
274
- if (!config.responseCookies) {
275
- config.responseCookies = {
276
- array: [],
277
- serialized: [],
278
- netscape: "",
279
- string: "",
280
- setCookiesString: []
281
- };
284
+ if (cookieHeaderArray.length === 0)
285
+ return;
286
+ const jar = new RezoCookieJar;
287
+ jar.setCookiesSync(cookieHeaderArray, url);
288
+ if (config.enableCookieJar && config.cookieJar) {
289
+ config.cookieJar.setCookiesSync(cookieHeaderArray, url);
282
290
  }
283
- for (const cookieStr of cookieHeaderArray) {
284
- config.responseCookies.setCookiesString.push(cookieStr);
285
- const parts = cookieStr.split(";");
286
- const [nameValue] = parts;
287
- const [name, ...valueParts] = nameValue.split("=");
288
- const value = valueParts.join("=");
289
- if (name && value !== undefined) {
290
- const cookie = new Cookie({
291
- key: name.trim(),
292
- value: value.trim(),
293
- domain: new URL(url).hostname,
294
- path: "/",
295
- httpOnly: cookieStr.toLowerCase().includes("httponly"),
296
- secure: cookieStr.toLowerCase().includes("secure"),
297
- sameSite: "lax"
298
- });
299
- config.responseCookies.array.push(cookie);
291
+ const cookies = jar.cookies();
292
+ cookies.setCookiesString = cookieHeaderArray;
293
+ if (config.useCookies) {
294
+ const existingArray = config.responseCookies?.array || [];
295
+ for (const cookie of cookies.array) {
296
+ const existingIndex = existingArray.findIndex((c) => c.key === cookie.key && c.domain === cookie.domain);
297
+ if (existingIndex >= 0) {
298
+ existingArray[existingIndex] = cookie;
299
+ } else {
300
+ existingArray.push(cookie);
301
+ }
300
302
  }
303
+ const mergedJar = new RezoCookieJar(existingArray, url);
304
+ config.responseCookies = mergedJar.cookies();
305
+ config.responseCookies.setCookiesString = cookieHeaderArray;
306
+ } else {
307
+ config.responseCookies = cookies;
301
308
  }
302
- config.responseCookies.string = config.responseCookies.array.map((c) => `${c.key}=${c.value}`).join("; ");
303
- config.responseCookies.serialized = config.responseCookies.array.map((c) => c.toJSON());
304
- config.responseCookies.netscape = config.responseCookies.array.map((c) => c.toNetscapeFormat()).join(`
305
- `);
309
+ }
310
+ function mergeRequestAndResponseCookies(config, responseCookies, url) {
311
+ const mergedCookiesArray = [];
312
+ const cookieKeyDomainMap = new Map;
313
+ if (config.requestCookies && config.requestCookies.length > 0) {
314
+ for (const cookie of config.requestCookies) {
315
+ const key = `${cookie.key}|${cookie.domain || ""}`;
316
+ mergedCookiesArray.push(cookie);
317
+ cookieKeyDomainMap.set(key, mergedCookiesArray.length - 1);
318
+ }
319
+ }
320
+ for (const cookie of responseCookies.array) {
321
+ const key = `${cookie.key}|${cookie.domain || ""}`;
322
+ const existingIndex = cookieKeyDomainMap.get(key);
323
+ if (existingIndex !== undefined) {
324
+ mergedCookiesArray[existingIndex] = cookie;
325
+ } else {
326
+ mergedCookiesArray.push(cookie);
327
+ cookieKeyDomainMap.set(key, mergedCookiesArray.length - 1);
328
+ }
329
+ }
330
+ if (mergedCookiesArray.length > 0) {
331
+ const mergedJar = new RezoCookieJar(mergedCookiesArray, url);
332
+ return mergedJar.cookies();
333
+ }
334
+ return {
335
+ array: [],
336
+ serialized: [],
337
+ netscape: `# Netscape HTTP Cookie File
338
+ # This file was generated by Rezo HTTP client
339
+ # Based on uniqhtt cookie implementation
340
+ `,
341
+ string: "",
342
+ setCookiesString: []
343
+ };
306
344
  }
307
345
  async function executeRequest(options, defaultOptions, jar) {
308
346
  if (!options.responseType) {
@@ -480,6 +518,8 @@ async function executeHttp2Request(fetchOptions, config, options, perform, fs, s
480
518
  if (fileName && fs && fs.existsSync(fileName)) {
481
519
  fs.unlinkSync(fileName);
482
520
  }
521
+ if (!config.errors)
522
+ config.errors = [];
483
523
  config.errors.push({
484
524
  attempt: config.retryAttempts + 1,
485
525
  error: response,
@@ -517,7 +557,7 @@ async function executeHttp2Request(fetchOptions, config, options, perform, fs, s
517
557
  }
518
558
  continue;
519
559
  }
520
- if (statusOnNext === "success") {
560
+ if (statusOnNext === "success" || statusOnNext === "error") {
521
561
  return response;
522
562
  }
523
563
  if (statusOnNext === "redirect") {
@@ -616,6 +656,13 @@ async function executeHttp2Stream(config, fetchOptions, requestCount, timing, _s
616
656
  if (!headers["accept-encoding"]) {
617
657
  headers["accept-encoding"] = "gzip, deflate, br";
618
658
  }
659
+ if (body instanceof RezoFormData) {
660
+ headers["content-type"] = `multipart/form-data; boundary=${body.getBoundary()}`;
661
+ } else if (body instanceof FormData) {
662
+ const tempForm = await RezoFormData.fromNativeFormData(body);
663
+ headers["content-type"] = `multipart/form-data; boundary=${tempForm.getBoundary()}`;
664
+ fetchOptions._convertedFormData = tempForm;
665
+ }
619
666
  const eventEmitter = streamResult || downloadResult || uploadResult;
620
667
  if (eventEmitter && requestCount === 0) {
621
668
  const startEvent = {
@@ -731,6 +778,25 @@ async function executeHttp2Stream(config, fetchOptions, requestCount, timing, _s
731
778
  config.timing.endTimestamp = Date.now();
732
779
  config.timing.durationMs = performance.now() - timing.startTime;
733
780
  config.timing.transferMs = timing.firstByteTime ? performance.now() - timing.firstByteTime : config.timing.durationMs;
781
+ if (!config.transfer) {
782
+ config.transfer = { requestSize: 0, responseSize: 0, headerSize: 0, bodySize: 0 };
783
+ }
784
+ if (config.transfer.requestSize === undefined) {
785
+ config.transfer.requestSize = 0;
786
+ }
787
+ if (config.transfer.requestSize === 0 && body) {
788
+ if (typeof body === "string") {
789
+ config.transfer.requestSize = Buffer.byteLength(body, "utf8");
790
+ } else if (body instanceof Buffer || body instanceof Uint8Array) {
791
+ config.transfer.requestSize = body.length;
792
+ } else if (body instanceof URLSearchParams || body instanceof RezoURLSearchParams) {
793
+ config.transfer.requestSize = Buffer.byteLength(body.toString(), "utf8");
794
+ } else if (body instanceof RezoFormData) {
795
+ config.transfer.requestSize = body.getLengthSync();
796
+ } else if (typeof body === "object") {
797
+ config.transfer.requestSize = Buffer.byteLength(JSON.stringify(body), "utf8");
798
+ }
799
+ }
734
800
  config.transfer.bodySize = contentLengthCounter;
735
801
  config.transfer.responseSize = contentLengthCounter;
736
802
  (sessionPool || Http2SessionPool.getInstance()).releaseSession(url);
@@ -739,7 +805,7 @@ async function executeHttp2Stream(config, fetchOptions, requestCount, timing, _s
739
805
  data: "",
740
806
  status,
741
807
  statusText,
742
- headers: new RezoHeaders(responseHeaders),
808
+ headers: new RezoHeaders(sanitizeHttp2Headers(responseHeaders)),
743
809
  cookies: config.responseCookies || { array: [], serialized: [], netscape: "", string: "", setCookiesString: [] },
744
810
  config,
745
811
  contentType: responseHeaders["content-type"],
@@ -752,14 +818,14 @@ async function executeHttp2Stream(config, fetchOptions, requestCount, timing, _s
752
818
  }
753
819
  let responseBody = Buffer.concat(chunks);
754
820
  const contentEncoding = responseHeaders["content-encoding"];
755
- if (contentEncoding && contentLengthCounter > 0) {
821
+ if (contentEncoding && contentLengthCounter > 0 && CompressionUtil.shouldDecompress(contentEncoding, config)) {
756
822
  try {
757
823
  const decompressed = await decompressBuffer(responseBody, contentEncoding);
758
824
  responseBody = decompressed;
759
825
  } catch (err) {
760
826
  const error = buildDecompressionError({
761
827
  statusCode: status,
762
- headers: responseHeaders,
828
+ headers: sanitizeHttp2Headers(responseHeaders),
763
829
  contentType: responseHeaders["content-type"],
764
830
  contentLength: String(contentLengthCounter),
765
831
  cookies: config.responseCookies?.setCookiesString || [],
@@ -799,24 +865,17 @@ async function executeHttp2Stream(config, fetchOptions, requestCount, timing, _s
799
865
  data = responseBody.toString("utf-8");
800
866
  }
801
867
  }
802
- if (status >= 400) {
803
- const error = builErrorFromResponse(`HTTP Error ${status}: ${statusText}`, {
804
- status,
805
- statusText,
806
- headers: new RezoHeaders(responseHeaders),
807
- data
808
- }, config, fetchOptions);
809
- _stats.statusOnNext = "error";
810
- resolve(error);
811
- return;
812
- }
813
- _stats.statusOnNext = "success";
868
+ config.status = status;
869
+ config.statusText = statusText;
870
+ _stats.statusOnNext = status >= 400 ? "error" : "success";
871
+ const responseCookies = config.responseCookies || { array: [], serialized: [], netscape: "", string: "", setCookiesString: [] };
872
+ const mergedCookies = mergeRequestAndResponseCookies(config, responseCookies, url.href);
814
873
  const finalResponse = {
815
874
  data,
816
875
  status,
817
876
  statusText,
818
- headers: new RezoHeaders(responseHeaders),
819
- cookies: config.responseCookies || { array: [], serialized: [], netscape: "", string: "", setCookiesString: [] },
877
+ headers: new RezoHeaders(sanitizeHttp2Headers(responseHeaders)),
878
+ cookies: mergedCookies,
820
879
  config,
821
880
  contentType,
822
881
  contentLength: contentLengthCounter,
@@ -829,11 +888,11 @@ async function executeHttp2Stream(config, fetchOptions, requestCount, timing, _s
829
888
  const downloadFinishEvent = {
830
889
  status,
831
890
  statusText,
832
- headers: new RezoHeaders(responseHeaders),
891
+ headers: new RezoHeaders(sanitizeHttp2Headers(responseHeaders)),
833
892
  contentType,
834
893
  contentLength: responseBody.length,
835
894
  finalUrl: url.href,
836
- cookies: config.responseCookies || { array: [], serialized: [], netscape: "", string: "", setCookiesString: [] },
895
+ cookies: mergedCookies,
837
896
  urls: buildUrlTree(config, url.href),
838
897
  fileName: config.fileName,
839
898
  fileSize: responseBody.length,
@@ -854,7 +913,7 @@ async function executeHttp2Stream(config, fetchOptions, requestCount, timing, _s
854
913
  } catch (err) {
855
914
  const error = buildDownloadError({
856
915
  statusCode: status,
857
- headers: responseHeaders,
916
+ headers: sanitizeHttp2Headers(responseHeaders),
858
917
  contentType,
859
918
  contentLength: String(contentLengthCounter),
860
919
  cookies: config.responseCookies?.setCookiesString || [],
@@ -874,7 +933,7 @@ async function executeHttp2Stream(config, fetchOptions, requestCount, timing, _s
874
933
  const streamFinishEvent = {
875
934
  status,
876
935
  statusText,
877
- headers: new RezoHeaders(responseHeaders),
936
+ headers: new RezoHeaders(sanitizeHttp2Headers(responseHeaders)),
878
937
  contentType,
879
938
  contentLength: contentLengthCounter,
880
939
  finalUrl: url.href,
@@ -900,7 +959,7 @@ async function executeHttp2Stream(config, fetchOptions, requestCount, timing, _s
900
959
  response: {
901
960
  status,
902
961
  statusText,
903
- headers: new RezoHeaders(responseHeaders),
962
+ headers: new RezoHeaders(sanitizeHttp2Headers(responseHeaders)),
904
963
  data,
905
964
  contentType,
906
965
  contentLength: contentLengthCounter
@@ -945,7 +1004,7 @@ async function executeHttp2Stream(config, fetchOptions, requestCount, timing, _s
945
1004
  body.pipe(req);
946
1005
  return;
947
1006
  } else {
948
- const form = await RezoFormData.fromNativeFormData(body);
1007
+ const form = fetchOptions._convertedFormData || await RezoFormData.fromNativeFormData(body);
949
1008
  form.pipe(req);
950
1009
  return;
951
1010
  }