rezo 1.0.137 → 1.0.138

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 (46) hide show
  1. package/dist/adapters/entries/curl.d.ts +17 -15
  2. package/dist/adapters/entries/fetch.d.ts +17 -15
  3. package/dist/adapters/entries/http.d.ts +17 -15
  4. package/dist/adapters/entries/http2.d.ts +17 -15
  5. package/dist/adapters/entries/react-native.cjs +6 -6
  6. package/dist/adapters/entries/react-native.d.ts +17 -15
  7. package/dist/adapters/entries/xhr.d.ts +17 -15
  8. package/dist/adapters/http.cjs +26 -0
  9. package/dist/adapters/http.js +26 -0
  10. package/dist/adapters/index.cjs +10 -10
  11. package/dist/adapters/index.d.ts +16 -14
  12. package/dist/cache/index.cjs +9 -9
  13. package/dist/cookies/cookie-jar.cjs +4 -4
  14. package/dist/cookies/index.cjs +10 -10
  15. package/dist/crawler/index.cjs +42 -42
  16. package/dist/crawler/plugin/index.cjs +1 -1
  17. package/dist/crawler.d.ts +16 -14
  18. package/dist/entries/crawler.cjs +24 -24
  19. package/dist/errors/rezo-error.cjs +3 -2
  20. package/dist/errors/rezo-error.js +3 -2
  21. package/dist/index.cjs +58 -58
  22. package/dist/index.d.ts +17 -15
  23. package/dist/internal/agents/index.cjs +14 -14
  24. package/dist/platform/browser.d.ts +17 -15
  25. package/dist/platform/bun.d.ts +17 -15
  26. package/dist/platform/deno.d.ts +17 -15
  27. package/dist/platform/node.d.ts +17 -15
  28. package/dist/platform/react-native.cjs +6 -6
  29. package/dist/platform/react-native.d.ts +17 -15
  30. package/dist/platform/worker.d.ts +17 -15
  31. package/dist/proxy/index.cjs +4 -4
  32. package/dist/queue/index.cjs +8 -8
  33. package/dist/responses/universal/index.cjs +11 -11
  34. package/dist/stealth/index.cjs +17 -17
  35. package/dist/stealth/profiles/index.cjs +10 -10
  36. package/dist/utils/agent-pool.cjs +1 -1
  37. package/dist/utils/agent-pool.js +1 -1
  38. package/dist/utils/http-config.cjs +15 -2
  39. package/dist/utils/http-config.js +15 -2
  40. package/dist/utils/staged-timeout.cjs +1 -2
  41. package/dist/utils/staged-timeout.js +1 -2
  42. package/dist/version.cjs +1 -1
  43. package/dist/version.js +1 -1
  44. package/dist/wget/index.cjs +51 -51
  45. package/dist/wget/index.d.ts +16 -14
  46. package/package.json +1 -1
@@ -2776,34 +2776,36 @@ export interface RezoRequestConfig<D = any> {
2776
2776
  * TLS negotiation for HTTPS).
2777
2777
  *
2778
2778
  * **Behavior:**
2779
- * - `false` (default) - Connection closes after each request. Process exits immediately.
2780
- * - `true` - Connection stays open for reuse. Idle connections close after `keepAliveMsecs`.
2779
+ * - `true` (default) - Connections are pooled and reused across requests to the
2780
+ * same host. Idle pooled sockets are closed after ~5 seconds.
2781
+ * - `false` - A fresh connection is opened for every request and closed after
2782
+ * the response. No pooling, no reuse.
2781
2783
  *
2782
- * **When to use `keepAlive: true`:**
2784
+ * **When to keep the default (`keepAlive: true`):**
2783
2785
  * - Making multiple requests to the same host in sequence
2784
2786
  * - Long-running applications (servers, bots, scrapers)
2785
2787
  * - Performance-critical applications where connection overhead matters
2786
2788
  *
2787
- * **When to use `keepAlive: false` (default):**
2788
- * - Single requests or scripts that should exit immediately
2789
- * - CLI tools that make one-off requests
2790
- * - When you need predictable process termination
2789
+ * **When to use `keepAlive: false`:**
2790
+ * - Hosts that reset reused connections aggressively
2791
+ * - Debugging connection-level issues (isolates every request)
2792
+ * - One-off requests where connection reuse buys nothing
2791
2793
  *
2792
2794
  * @example
2793
2795
  * ```typescript
2794
- * // Default: process exits immediately after request
2796
+ * // Default: pooled keep-alive connections
2795
2797
  * const { data } = await rezo.get('https://api.example.com/data');
2796
2798
  *
2797
- * // Keep connection alive for 1 minute (default) for subsequent requests
2798
- * const client = new Rezo({ keepAlive: true });
2799
+ * // Fresh connection per request for this instance
2800
+ * const client = rezo.create({ keepAlive: false });
2799
2801
  * await client.get('https://api.example.com/users');
2800
- * await client.get('https://api.example.com/posts'); // Reuses connection
2802
+ * await client.get('https://api.example.com/posts'); // New connection again
2801
2803
  *
2802
- * // Custom keep-alive timeout (30 seconds)
2803
- * const client = new Rezo({ keepAlive: true, keepAliveMsecs: 30000 });
2804
+ * // Or per request
2805
+ * await rezo.get('https://api.example.com/data', { keepAlive: false });
2804
2806
  * ```
2805
2807
  *
2806
- * @default false
2808
+ * @default true
2807
2809
  */
2808
2810
  keepAlive?: boolean;
2809
2811
  /**
@@ -8581,7 +8583,7 @@ export interface RezoInstance extends Rezo, RezoCallable {
8581
8583
  *
8582
8584
  * IMPORTANT: Update these values when bumping package version.
8583
8585
  */
8584
- export declare const VERSION = "1.0.137";
8586
+ export declare const VERSION = "1.0.138";
8585
8587
  export declare const isRezoError: typeof RezoError.isRezoError;
8586
8588
  export declare const Cancel: typeof RezoError;
8587
8589
  export declare const CancelToken: {
@@ -4103,34 +4103,36 @@ export interface RezoRequestConfig<D = any> {
4103
4103
  * TLS negotiation for HTTPS).
4104
4104
  *
4105
4105
  * **Behavior:**
4106
- * - `false` (default) - Connection closes after each request. Process exits immediately.
4107
- * - `true` - Connection stays open for reuse. Idle connections close after `keepAliveMsecs`.
4106
+ * - `true` (default) - Connections are pooled and reused across requests to the
4107
+ * same host. Idle pooled sockets are closed after ~5 seconds.
4108
+ * - `false` - A fresh connection is opened for every request and closed after
4109
+ * the response. No pooling, no reuse.
4108
4110
  *
4109
- * **When to use `keepAlive: true`:**
4111
+ * **When to keep the default (`keepAlive: true`):**
4110
4112
  * - Making multiple requests to the same host in sequence
4111
4113
  * - Long-running applications (servers, bots, scrapers)
4112
4114
  * - Performance-critical applications where connection overhead matters
4113
4115
  *
4114
- * **When to use `keepAlive: false` (default):**
4115
- * - Single requests or scripts that should exit immediately
4116
- * - CLI tools that make one-off requests
4117
- * - When you need predictable process termination
4116
+ * **When to use `keepAlive: false`:**
4117
+ * - Hosts that reset reused connections aggressively
4118
+ * - Debugging connection-level issues (isolates every request)
4119
+ * - One-off requests where connection reuse buys nothing
4118
4120
  *
4119
4121
  * @example
4120
4122
  * ```typescript
4121
- * // Default: process exits immediately after request
4123
+ * // Default: pooled keep-alive connections
4122
4124
  * const { data } = await rezo.get('https://api.example.com/data');
4123
4125
  *
4124
- * // Keep connection alive for 1 minute (default) for subsequent requests
4125
- * const client = new Rezo({ keepAlive: true });
4126
+ * // Fresh connection per request for this instance
4127
+ * const client = rezo.create({ keepAlive: false });
4126
4128
  * await client.get('https://api.example.com/users');
4127
- * await client.get('https://api.example.com/posts'); // Reuses connection
4129
+ * await client.get('https://api.example.com/posts'); // New connection again
4128
4130
  *
4129
- * // Custom keep-alive timeout (30 seconds)
4130
- * const client = new Rezo({ keepAlive: true, keepAliveMsecs: 30000 });
4131
+ * // Or per request
4132
+ * await rezo.get('https://api.example.com/data', { keepAlive: false });
4131
4133
  * ```
4132
4134
  *
4133
- * @default false
4135
+ * @default true
4134
4136
  */
4135
4137
  keepAlive?: boolean;
4136
4138
  /**
@@ -6096,7 +6098,7 @@ export interface RezoInstance extends Rezo, RezoCallable {
6096
6098
  *
6097
6099
  * IMPORTANT: Update these values when bumping package version.
6098
6100
  */
6099
- export declare const VERSION = "1.0.137";
6101
+ export declare const VERSION = "1.0.138";
6100
6102
  export declare const isRezoError: typeof RezoError.isRezoError;
6101
6103
  export declare const Cancel: typeof RezoError;
6102
6104
  export declare const CancelToken: {
@@ -4103,34 +4103,36 @@ export interface RezoRequestConfig<D = any> {
4103
4103
  * TLS negotiation for HTTPS).
4104
4104
  *
4105
4105
  * **Behavior:**
4106
- * - `false` (default) - Connection closes after each request. Process exits immediately.
4107
- * - `true` - Connection stays open for reuse. Idle connections close after `keepAliveMsecs`.
4106
+ * - `true` (default) - Connections are pooled and reused across requests to the
4107
+ * same host. Idle pooled sockets are closed after ~5 seconds.
4108
+ * - `false` - A fresh connection is opened for every request and closed after
4109
+ * the response. No pooling, no reuse.
4108
4110
  *
4109
- * **When to use `keepAlive: true`:**
4111
+ * **When to keep the default (`keepAlive: true`):**
4110
4112
  * - Making multiple requests to the same host in sequence
4111
4113
  * - Long-running applications (servers, bots, scrapers)
4112
4114
  * - Performance-critical applications where connection overhead matters
4113
4115
  *
4114
- * **When to use `keepAlive: false` (default):**
4115
- * - Single requests or scripts that should exit immediately
4116
- * - CLI tools that make one-off requests
4117
- * - When you need predictable process termination
4116
+ * **When to use `keepAlive: false`:**
4117
+ * - Hosts that reset reused connections aggressively
4118
+ * - Debugging connection-level issues (isolates every request)
4119
+ * - One-off requests where connection reuse buys nothing
4118
4120
  *
4119
4121
  * @example
4120
4122
  * ```typescript
4121
- * // Default: process exits immediately after request
4123
+ * // Default: pooled keep-alive connections
4122
4124
  * const { data } = await rezo.get('https://api.example.com/data');
4123
4125
  *
4124
- * // Keep connection alive for 1 minute (default) for subsequent requests
4125
- * const client = new Rezo({ keepAlive: true });
4126
+ * // Fresh connection per request for this instance
4127
+ * const client = rezo.create({ keepAlive: false });
4126
4128
  * await client.get('https://api.example.com/users');
4127
- * await client.get('https://api.example.com/posts'); // Reuses connection
4129
+ * await client.get('https://api.example.com/posts'); // New connection again
4128
4130
  *
4129
- * // Custom keep-alive timeout (30 seconds)
4130
- * const client = new Rezo({ keepAlive: true, keepAliveMsecs: 30000 });
4131
+ * // Or per request
4132
+ * await rezo.get('https://api.example.com/data', { keepAlive: false });
4131
4133
  * ```
4132
4134
  *
4133
- * @default false
4135
+ * @default true
4134
4136
  */
4135
4137
  keepAlive?: boolean;
4136
4138
  /**
@@ -6171,7 +6173,7 @@ export declare function getSocketTelemetry(socket: Socket): SocketTelemetry | un
6171
6173
  *
6172
6174
  * IMPORTANT: Update these values when bumping package version.
6173
6175
  */
6174
- export declare const VERSION = "1.0.137";
6176
+ export declare const VERSION = "1.0.138";
6175
6177
  /**
6176
6178
  * Type guard to check if an error is a RezoError instance.
6177
6179
  */
@@ -4104,34 +4104,36 @@ export interface RezoRequestConfig<D = any> {
4104
4104
  * TLS negotiation for HTTPS).
4105
4105
  *
4106
4106
  * **Behavior:**
4107
- * - `false` (default) - Connection closes after each request. Process exits immediately.
4108
- * - `true` - Connection stays open for reuse. Idle connections close after `keepAliveMsecs`.
4107
+ * - `true` (default) - Connections are pooled and reused across requests to the
4108
+ * same host. Idle pooled sockets are closed after ~5 seconds.
4109
+ * - `false` - A fresh connection is opened for every request and closed after
4110
+ * the response. No pooling, no reuse.
4109
4111
  *
4110
- * **When to use `keepAlive: true`:**
4112
+ * **When to keep the default (`keepAlive: true`):**
4111
4113
  * - Making multiple requests to the same host in sequence
4112
4114
  * - Long-running applications (servers, bots, scrapers)
4113
4115
  * - Performance-critical applications where connection overhead matters
4114
4116
  *
4115
- * **When to use `keepAlive: false` (default):**
4116
- * - Single requests or scripts that should exit immediately
4117
- * - CLI tools that make one-off requests
4118
- * - When you need predictable process termination
4117
+ * **When to use `keepAlive: false`:**
4118
+ * - Hosts that reset reused connections aggressively
4119
+ * - Debugging connection-level issues (isolates every request)
4120
+ * - One-off requests where connection reuse buys nothing
4119
4121
  *
4120
4122
  * @example
4121
4123
  * ```typescript
4122
- * // Default: process exits immediately after request
4124
+ * // Default: pooled keep-alive connections
4123
4125
  * const { data } = await rezo.get('https://api.example.com/data');
4124
4126
  *
4125
- * // Keep connection alive for 1 minute (default) for subsequent requests
4126
- * const client = new Rezo({ keepAlive: true });
4127
+ * // Fresh connection per request for this instance
4128
+ * const client = rezo.create({ keepAlive: false });
4127
4129
  * await client.get('https://api.example.com/users');
4128
- * await client.get('https://api.example.com/posts'); // Reuses connection
4130
+ * await client.get('https://api.example.com/posts'); // New connection again
4129
4131
  *
4130
- * // Custom keep-alive timeout (30 seconds)
4131
- * const client = new Rezo({ keepAlive: true, keepAliveMsecs: 30000 });
4132
+ * // Or per request
4133
+ * await rezo.get('https://api.example.com/data', { keepAlive: false });
4132
4134
  * ```
4133
4135
  *
4134
- * @default false
4136
+ * @default true
4135
4137
  */
4136
4138
  keepAlive?: boolean;
4137
4139
  /**
@@ -6122,7 +6124,7 @@ export interface RezoInstance extends Rezo, RezoCallable {
6122
6124
  *
6123
6125
  * IMPORTANT: Update these values when bumping package version.
6124
6126
  */
6125
- export declare const VERSION = "1.0.137";
6127
+ export declare const VERSION = "1.0.138";
6126
6128
  export declare const isRezoError: typeof RezoError.isRezoError;
6127
6129
  export declare const Cancel: typeof RezoError;
6128
6130
  export declare const CancelToken: {
@@ -6,12 +6,12 @@ const { RezoFormData } = require('../../utils/form-data.cjs');
6
6
  const { RezoCookieJar, Cookie } = require('../../cookies/cookie-jar.cjs');
7
7
  const { createDefaultHooks, mergeHooks } = require('../../core/hooks.cjs');
8
8
  const { VERSION } = require('../../version.cjs');
9
- const _mod_bxvwu1 = require('../../platform/react-native-providers.cjs');
10
- exports.createFetchStreamTransport = _mod_bxvwu1.createFetchStreamTransport;
11
- exports.createExpoFileSystemAdapter = _mod_bxvwu1.createExpoFileSystemAdapter;
12
- exports.createReactNativeFsAdapter = _mod_bxvwu1.createReactNativeFsAdapter;
13
- exports.createNetInfoProvider = _mod_bxvwu1.createNetInfoProvider;
14
- exports.createExpoBackgroundTaskProvider = _mod_bxvwu1.createExpoBackgroundTaskProvider;;
9
+ const _mod_uyu65l = require('../../platform/react-native-providers.cjs');
10
+ exports.createFetchStreamTransport = _mod_uyu65l.createFetchStreamTransport;
11
+ exports.createExpoFileSystemAdapter = _mod_uyu65l.createExpoFileSystemAdapter;
12
+ exports.createReactNativeFsAdapter = _mod_uyu65l.createReactNativeFsAdapter;
13
+ exports.createNetInfoProvider = _mod_uyu65l.createNetInfoProvider;
14
+ exports.createExpoBackgroundTaskProvider = _mod_uyu65l.createExpoBackgroundTaskProvider;;
15
15
  exports.Rezo = Rezo;
16
16
  exports.RezoError = RezoError;
17
17
  exports.RezoErrorCode = RezoErrorCode;
@@ -4103,34 +4103,36 @@ export interface RezoRequestConfig<D = any> {
4103
4103
  * TLS negotiation for HTTPS).
4104
4104
  *
4105
4105
  * **Behavior:**
4106
- * - `false` (default) - Connection closes after each request. Process exits immediately.
4107
- * - `true` - Connection stays open for reuse. Idle connections close after `keepAliveMsecs`.
4106
+ * - `true` (default) - Connections are pooled and reused across requests to the
4107
+ * same host. Idle pooled sockets are closed after ~5 seconds.
4108
+ * - `false` - A fresh connection is opened for every request and closed after
4109
+ * the response. No pooling, no reuse.
4108
4110
  *
4109
- * **When to use `keepAlive: true`:**
4111
+ * **When to keep the default (`keepAlive: true`):**
4110
4112
  * - Making multiple requests to the same host in sequence
4111
4113
  * - Long-running applications (servers, bots, scrapers)
4112
4114
  * - Performance-critical applications where connection overhead matters
4113
4115
  *
4114
- * **When to use `keepAlive: false` (default):**
4115
- * - Single requests or scripts that should exit immediately
4116
- * - CLI tools that make one-off requests
4117
- * - When you need predictable process termination
4116
+ * **When to use `keepAlive: false`:**
4117
+ * - Hosts that reset reused connections aggressively
4118
+ * - Debugging connection-level issues (isolates every request)
4119
+ * - One-off requests where connection reuse buys nothing
4118
4120
  *
4119
4121
  * @example
4120
4122
  * ```typescript
4121
- * // Default: process exits immediately after request
4123
+ * // Default: pooled keep-alive connections
4122
4124
  * const { data } = await rezo.get('https://api.example.com/data');
4123
4125
  *
4124
- * // Keep connection alive for 1 minute (default) for subsequent requests
4125
- * const client = new Rezo({ keepAlive: true });
4126
+ * // Fresh connection per request for this instance
4127
+ * const client = rezo.create({ keepAlive: false });
4126
4128
  * await client.get('https://api.example.com/users');
4127
- * await client.get('https://api.example.com/posts'); // Reuses connection
4129
+ * await client.get('https://api.example.com/posts'); // New connection again
4128
4130
  *
4129
- * // Custom keep-alive timeout (30 seconds)
4130
- * const client = new Rezo({ keepAlive: true, keepAliveMsecs: 30000 });
4131
+ * // Or per request
4132
+ * await rezo.get('https://api.example.com/data', { keepAlive: false });
4131
4133
  * ```
4132
4134
  *
4133
- * @default false
4135
+ * @default true
4134
4136
  */
4135
4137
  keepAlive?: boolean;
4136
4138
  /**
@@ -6096,7 +6098,7 @@ export interface RezoInstance extends Rezo, RezoCallable {
6096
6098
  *
6097
6099
  * IMPORTANT: Update these values when bumping package version.
6098
6100
  */
6099
- export declare const VERSION = "1.0.137";
6101
+ export declare const VERSION = "1.0.138";
6100
6102
  export interface ExpoFileSystemFileLike {
6101
6103
  uri?: string;
6102
6104
  size?: number;
@@ -4103,34 +4103,36 @@ export interface RezoRequestConfig<D = any> {
4103
4103
  * TLS negotiation for HTTPS).
4104
4104
  *
4105
4105
  * **Behavior:**
4106
- * - `false` (default) - Connection closes after each request. Process exits immediately.
4107
- * - `true` - Connection stays open for reuse. Idle connections close after `keepAliveMsecs`.
4106
+ * - `true` (default) - Connections are pooled and reused across requests to the
4107
+ * same host. Idle pooled sockets are closed after ~5 seconds.
4108
+ * - `false` - A fresh connection is opened for every request and closed after
4109
+ * the response. No pooling, no reuse.
4108
4110
  *
4109
- * **When to use `keepAlive: true`:**
4111
+ * **When to keep the default (`keepAlive: true`):**
4110
4112
  * - Making multiple requests to the same host in sequence
4111
4113
  * - Long-running applications (servers, bots, scrapers)
4112
4114
  * - Performance-critical applications where connection overhead matters
4113
4115
  *
4114
- * **When to use `keepAlive: false` (default):**
4115
- * - Single requests or scripts that should exit immediately
4116
- * - CLI tools that make one-off requests
4117
- * - When you need predictable process termination
4116
+ * **When to use `keepAlive: false`:**
4117
+ * - Hosts that reset reused connections aggressively
4118
+ * - Debugging connection-level issues (isolates every request)
4119
+ * - One-off requests where connection reuse buys nothing
4118
4120
  *
4119
4121
  * @example
4120
4122
  * ```typescript
4121
- * // Default: process exits immediately after request
4123
+ * // Default: pooled keep-alive connections
4122
4124
  * const { data } = await rezo.get('https://api.example.com/data');
4123
4125
  *
4124
- * // Keep connection alive for 1 minute (default) for subsequent requests
4125
- * const client = new Rezo({ keepAlive: true });
4126
+ * // Fresh connection per request for this instance
4127
+ * const client = rezo.create({ keepAlive: false });
4126
4128
  * await client.get('https://api.example.com/users');
4127
- * await client.get('https://api.example.com/posts'); // Reuses connection
4129
+ * await client.get('https://api.example.com/posts'); // New connection again
4128
4130
  *
4129
- * // Custom keep-alive timeout (30 seconds)
4130
- * const client = new Rezo({ keepAlive: true, keepAliveMsecs: 30000 });
4131
+ * // Or per request
4132
+ * await rezo.get('https://api.example.com/data', { keepAlive: false });
4131
4133
  * ```
4132
4134
  *
4133
- * @default false
4135
+ * @default true
4134
4136
  */
4135
4137
  keepAlive?: boolean;
4136
4138
  /**
@@ -6096,7 +6098,7 @@ export interface RezoInstance extends Rezo, RezoCallable {
6096
6098
  *
6097
6099
  * IMPORTANT: Update these values when bumping package version.
6098
6100
  */
6099
- export declare const VERSION = "1.0.137";
6101
+ export declare const VERSION = "1.0.138";
6100
6102
  export declare const isRezoError: typeof RezoError.isRezoError;
6101
6103
  export declare const Cancel: typeof RezoError;
6102
6104
  export declare const CancelToken: {
@@ -382,6 +382,7 @@ async function executeHttp1Request(fetchOptions, config, options, perform, fs, s
382
382
  const ABSOLUTE_MAX_ATTEMPTS = 50;
383
383
  const visitedUrls = new Set;
384
384
  let totalAttempts = 0;
385
+ let staleSocketRetried = false;
385
386
  config.setSignal();
386
387
  const timeoutClearInstance = config.timeoutClearInstance;
387
388
  delete config.timeoutClearInstance;
@@ -414,6 +415,15 @@ async function executeHttp1Request(fetchOptions, config, options, perform, fs, s
414
415
  duration: perform.now()
415
416
  });
416
417
  perform.reset();
418
+ if (response.isStaleSocketReset && !staleSocketRetried) {
419
+ const staleMethod = (fetchOptions.method || "GET").toUpperCase();
420
+ const staleBody = fetchOptions.body;
421
+ const bodyReplayable = staleBody === undefined || staleBody === null || typeof staleBody === "string" || Buffer.isBuffer(staleBody);
422
+ if (["GET", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE"].includes(staleMethod) && bodyReplayable) {
423
+ staleSocketRetried = true;
424
+ continue;
425
+ }
426
+ }
417
427
  if (!retryConfig) {
418
428
  throw response;
419
429
  }
@@ -734,8 +744,11 @@ async function request(config, fetchOptions, requestCount, timing, _stats, _resp
734
744
  if (timeoutManager.hasPhase("total")) {
735
745
  timeoutManager.startPhase("total");
736
746
  }
747
+ let connectionWasReused = false;
748
+ let responseReceived = false;
737
749
  try {
738
750
  const req = httpModule.request(requestOptions, async (res) => {
751
+ responseReceived = true;
739
752
  timeoutManager.clearPhase("headers");
740
753
  if (timeoutManager.hasPhase("body")) {
741
754
  timeoutManager.startPhase("body");
@@ -859,6 +872,8 @@ async function request(config, fetchOptions, requestCount, timing, _stats, _resp
859
872
  let contentLengthCounter = 0;
860
873
  if (streamResult) {
861
874
  if (isRedirected) {
875
+ timeoutManager.clearAll();
876
+ res.resume();
862
877
  resolve(null);
863
878
  return;
864
879
  }
@@ -1134,6 +1149,9 @@ async function request(config, fetchOptions, requestCount, timing, _stats, _resp
1134
1149
  }
1135
1150
  }
1136
1151
  const error = buildSmartError(config, fetchOptions, err);
1152
+ if (err?.code === "ECONNRESET" && connectionWasReused && !responseReceived) {
1153
+ error.isStaleSocketReset = true;
1154
+ }
1137
1155
  resolve(error);
1138
1156
  });
1139
1157
  req.on("socket", (socket) => {
@@ -1164,6 +1182,7 @@ async function request(config, fetchOptions, requestCount, timing, _stats, _resp
1164
1182
  });
1165
1183
  const reqContext = beginRequestContext(socket, isSecure);
1166
1184
  const telemetry = getSocketTelemetry(socket);
1185
+ connectionWasReused = reqContext.connectionReused;
1167
1186
  if (reqContext.connectionReused) {
1168
1187
  timeoutManager.clearPhase("connect");
1169
1188
  if (timeoutManager.hasPhase("headers")) {
@@ -1531,6 +1550,13 @@ function buildHTTPOptions(fetchOptions, isSecure, url) {
1531
1550
  keepAlive,
1532
1551
  keepAliveMsecs: keepAlive ? keepAliveMsecs : undefined
1533
1552
  });
1553
+ } else if (keepAlive === false) {
1554
+ agent = isSecure ? new https.Agent({
1555
+ keepAlive: false,
1556
+ ...useSecureContext ? { secureContext: createSecureContext() } : {},
1557
+ servername: url.hostname,
1558
+ rejectUnauthorized
1559
+ }) : new http.Agent({ keepAlive: false });
1534
1560
  } else if (useAgentPool) {
1535
1561
  const agentPool = getGlobalAgentPool({
1536
1562
  keepAlive: true,
@@ -382,6 +382,7 @@ async function executeHttp1Request(fetchOptions, config, options, perform, fs, s
382
382
  const ABSOLUTE_MAX_ATTEMPTS = 50;
383
383
  const visitedUrls = new Set;
384
384
  let totalAttempts = 0;
385
+ let staleSocketRetried = false;
385
386
  config.setSignal();
386
387
  const timeoutClearInstance = config.timeoutClearInstance;
387
388
  delete config.timeoutClearInstance;
@@ -414,6 +415,15 @@ async function executeHttp1Request(fetchOptions, config, options, perform, fs, s
414
415
  duration: perform.now()
415
416
  });
416
417
  perform.reset();
418
+ if (response.isStaleSocketReset && !staleSocketRetried) {
419
+ const staleMethod = (fetchOptions.method || "GET").toUpperCase();
420
+ const staleBody = fetchOptions.body;
421
+ const bodyReplayable = staleBody === undefined || staleBody === null || typeof staleBody === "string" || Buffer.isBuffer(staleBody);
422
+ if (["GET", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE"].includes(staleMethod) && bodyReplayable) {
423
+ staleSocketRetried = true;
424
+ continue;
425
+ }
426
+ }
417
427
  if (!retryConfig) {
418
428
  throw response;
419
429
  }
@@ -734,8 +744,11 @@ async function request(config, fetchOptions, requestCount, timing, _stats, _resp
734
744
  if (timeoutManager.hasPhase("total")) {
735
745
  timeoutManager.startPhase("total");
736
746
  }
747
+ let connectionWasReused = false;
748
+ let responseReceived = false;
737
749
  try {
738
750
  const req = httpModule.request(requestOptions, async (res) => {
751
+ responseReceived = true;
739
752
  timeoutManager.clearPhase("headers");
740
753
  if (timeoutManager.hasPhase("body")) {
741
754
  timeoutManager.startPhase("body");
@@ -859,6 +872,8 @@ async function request(config, fetchOptions, requestCount, timing, _stats, _resp
859
872
  let contentLengthCounter = 0;
860
873
  if (streamResult) {
861
874
  if (isRedirected) {
875
+ timeoutManager.clearAll();
876
+ res.resume();
862
877
  resolve(null);
863
878
  return;
864
879
  }
@@ -1134,6 +1149,9 @@ async function request(config, fetchOptions, requestCount, timing, _stats, _resp
1134
1149
  }
1135
1150
  }
1136
1151
  const error = buildSmartError(config, fetchOptions, err);
1152
+ if (err?.code === "ECONNRESET" && connectionWasReused && !responseReceived) {
1153
+ error.isStaleSocketReset = true;
1154
+ }
1137
1155
  resolve(error);
1138
1156
  });
1139
1157
  req.on("socket", (socket) => {
@@ -1164,6 +1182,7 @@ async function request(config, fetchOptions, requestCount, timing, _stats, _resp
1164
1182
  });
1165
1183
  const reqContext = beginRequestContext(socket, isSecure);
1166
1184
  const telemetry = getSocketTelemetry(socket);
1185
+ connectionWasReused = reqContext.connectionReused;
1167
1186
  if (reqContext.connectionReused) {
1168
1187
  timeoutManager.clearPhase("connect");
1169
1188
  if (timeoutManager.hasPhase("headers")) {
@@ -1531,6 +1550,13 @@ function buildHTTPOptions(fetchOptions, isSecure, url) {
1531
1550
  keepAlive,
1532
1551
  keepAliveMsecs: keepAlive ? keepAliveMsecs : undefined
1533
1552
  });
1553
+ } else if (keepAlive === false) {
1554
+ agent = isSecure ? new https.Agent({
1555
+ keepAlive: false,
1556
+ ...useSecureContext ? { secureContext: createSecureContext() } : {},
1557
+ servername: url.hostname,
1558
+ rejectUnauthorized
1559
+ }) : new http.Agent({ keepAlive: false });
1534
1560
  } else if (useAgentPool) {
1535
1561
  const agentPool = getGlobalAgentPool({
1536
1562
  keepAlive: true,
@@ -1,10 +1,10 @@
1
- const _mod_d6ixx4 = require('./picker.cjs');
2
- exports.detectRuntime = _mod_d6ixx4.detectRuntime;
3
- exports.getAdapterCapabilities = _mod_d6ixx4.getAdapterCapabilities;
4
- exports.buildAdapterContext = _mod_d6ixx4.buildAdapterContext;
5
- exports.getAvailableAdapters = _mod_d6ixx4.getAvailableAdapters;
6
- exports.selectAdapter = _mod_d6ixx4.selectAdapter;
7
- exports.getAdapterDiagnostics = _mod_d6ixx4.getAdapterDiagnostics;
8
- exports.createAdapterPicker = _mod_d6ixx4.createAdapterPicker;
9
- exports.clearAdapterCache = _mod_d6ixx4.clearAdapterCache;
10
- exports.loadAdapter = _mod_d6ixx4.loadAdapter;;
1
+ const _mod_jy8lw5 = require('./picker.cjs');
2
+ exports.detectRuntime = _mod_jy8lw5.detectRuntime;
3
+ exports.getAdapterCapabilities = _mod_jy8lw5.getAdapterCapabilities;
4
+ exports.buildAdapterContext = _mod_jy8lw5.buildAdapterContext;
5
+ exports.getAvailableAdapters = _mod_jy8lw5.getAvailableAdapters;
6
+ exports.selectAdapter = _mod_jy8lw5.selectAdapter;
7
+ exports.getAdapterDiagnostics = _mod_jy8lw5.getAdapterDiagnostics;
8
+ exports.createAdapterPicker = _mod_jy8lw5.createAdapterPicker;
9
+ exports.clearAdapterCache = _mod_jy8lw5.clearAdapterCache;
10
+ exports.loadAdapter = _mod_jy8lw5.loadAdapter;;
@@ -4028,34 +4028,36 @@ export interface RezoRequestConfig<D = any> {
4028
4028
  * TLS negotiation for HTTPS).
4029
4029
  *
4030
4030
  * **Behavior:**
4031
- * - `false` (default) - Connection closes after each request. Process exits immediately.
4032
- * - `true` - Connection stays open for reuse. Idle connections close after `keepAliveMsecs`.
4031
+ * - `true` (default) - Connections are pooled and reused across requests to the
4032
+ * same host. Idle pooled sockets are closed after ~5 seconds.
4033
+ * - `false` - A fresh connection is opened for every request and closed after
4034
+ * the response. No pooling, no reuse.
4033
4035
  *
4034
- * **When to use `keepAlive: true`:**
4036
+ * **When to keep the default (`keepAlive: true`):**
4035
4037
  * - Making multiple requests to the same host in sequence
4036
4038
  * - Long-running applications (servers, bots, scrapers)
4037
4039
  * - Performance-critical applications where connection overhead matters
4038
4040
  *
4039
- * **When to use `keepAlive: false` (default):**
4040
- * - Single requests or scripts that should exit immediately
4041
- * - CLI tools that make one-off requests
4042
- * - When you need predictable process termination
4041
+ * **When to use `keepAlive: false`:**
4042
+ * - Hosts that reset reused connections aggressively
4043
+ * - Debugging connection-level issues (isolates every request)
4044
+ * - One-off requests where connection reuse buys nothing
4043
4045
  *
4044
4046
  * @example
4045
4047
  * ```typescript
4046
- * // Default: process exits immediately after request
4048
+ * // Default: pooled keep-alive connections
4047
4049
  * const { data } = await rezo.get('https://api.example.com/data');
4048
4050
  *
4049
- * // Keep connection alive for 1 minute (default) for subsequent requests
4050
- * const client = new Rezo({ keepAlive: true });
4051
+ * // Fresh connection per request for this instance
4052
+ * const client = rezo.create({ keepAlive: false });
4051
4053
  * await client.get('https://api.example.com/users');
4052
- * await client.get('https://api.example.com/posts'); // Reuses connection
4054
+ * await client.get('https://api.example.com/posts'); // New connection again
4053
4055
  *
4054
- * // Custom keep-alive timeout (30 seconds)
4055
- * const client = new Rezo({ keepAlive: true, keepAliveMsecs: 30000 });
4056
+ * // Or per request
4057
+ * await rezo.get('https://api.example.com/data', { keepAlive: false });
4056
4058
  * ```
4057
4059
  *
4058
- * @default false
4060
+ * @default true
4059
4061
  */
4060
4062
  keepAlive?: boolean;
4061
4063
  /**
@@ -1,9 +1,9 @@
1
- const _mod_i4ek3a = require('./lru-cache.cjs');
2
- exports.LRUCache = _mod_i4ek3a.LRUCache;;
3
- const _mod_ekaq2h = require('./dns-cache.cjs');
4
- exports.DNSCache = _mod_ekaq2h.DNSCache;
5
- exports.getGlobalDNSCache = _mod_ekaq2h.getGlobalDNSCache;
6
- exports.resetGlobalDNSCache = _mod_ekaq2h.resetGlobalDNSCache;;
7
- const _mod_6jt456 = require('./response-cache.cjs');
8
- exports.ResponseCache = _mod_6jt456.ResponseCache;
9
- exports.normalizeResponseCacheConfig = _mod_6jt456.normalizeResponseCacheConfig;;
1
+ const _mod_a07f40 = require('./lru-cache.cjs');
2
+ exports.LRUCache = _mod_a07f40.LRUCache;;
3
+ const _mod_e8bo0m = require('./dns-cache.cjs');
4
+ exports.DNSCache = _mod_e8bo0m.DNSCache;
5
+ exports.getGlobalDNSCache = _mod_e8bo0m.getGlobalDNSCache;
6
+ exports.resetGlobalDNSCache = _mod_e8bo0m.resetGlobalDNSCache;;
7
+ const _mod_xklic4 = require('./response-cache.cjs');
8
+ exports.ResponseCache = _mod_xklic4.ResponseCache;
9
+ exports.normalizeResponseCacheConfig = _mod_xklic4.normalizeResponseCacheConfig;;