rezo 1.0.107 → 1.0.108
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.
- package/dist/adapters/curl.cjs +138 -53
- package/dist/adapters/curl.js +138 -53
- package/dist/adapters/entries/curl.d.ts +82 -1
- package/dist/adapters/entries/fetch.d.ts +82 -1
- package/dist/adapters/entries/http.d.ts +82 -1
- package/dist/adapters/entries/http2.d.ts +82 -1
- package/dist/adapters/entries/react-native.d.ts +82 -1
- package/dist/adapters/entries/xhr.d.ts +82 -1
- package/dist/adapters/fetch.cjs +2 -1
- package/dist/adapters/fetch.js +2 -1
- package/dist/adapters/http.cjs +5 -2
- package/dist/adapters/http.js +5 -2
- package/dist/adapters/http2.cjs +2 -1
- package/dist/adapters/http2.js +2 -1
- package/dist/adapters/index.cjs +6 -6
- package/dist/adapters/react-native.cjs +2 -1
- package/dist/adapters/react-native.js +2 -1
- package/dist/adapters/xhr.cjs +2 -1
- package/dist/adapters/xhr.js +2 -1
- package/dist/cache/index.cjs +9 -9
- package/dist/cookies/cookie-jar.cjs +6 -5
- package/dist/cookies/cookie-jar.js +2 -1
- package/dist/cookies/index.cjs +10 -10
- package/dist/crawler/index.cjs +42 -42
- package/dist/crawler/plugin/index.cjs +1 -1
- package/dist/crawler.d.ts +81 -0
- package/dist/entries/crawler.cjs +6 -6
- package/dist/index.cjs +44 -44
- package/dist/index.d.ts +82 -1
- package/dist/internal/agents/index.cjs +14 -14
- package/dist/platform/browser.d.ts +82 -1
- package/dist/platform/bun.d.ts +82 -1
- package/dist/platform/deno.d.ts +82 -1
- package/dist/platform/node.d.ts +82 -1
- package/dist/platform/react-native.d.ts +82 -1
- package/dist/platform/worker.d.ts +82 -1
- package/dist/proxy/index.cjs +4 -4
- package/dist/queue/index.cjs +9 -9
- package/dist/responses/buildResponse.cjs +22 -8
- package/dist/responses/buildResponse.js +22 -8
- package/dist/responses/universal/index.cjs +11 -11
- package/dist/stealth/index.cjs +17 -17
- package/dist/stealth/profiles/index.cjs +10 -10
- package/dist/utils/headers.cjs +27 -2
- package/dist/utils/headers.js +27 -2
- package/dist/utils/http-config.cjs +28 -7
- package/dist/utils/http-config.js +28 -7
- package/dist/version.cjs +1 -1
- package/dist/version.js +1 -1
- package/dist/wget/index.cjs +51 -51
- package/dist/wget/index.d.ts +81 -0
- package/package.json +1 -1
package/dist/adapters/curl.cjs
CHANGED
|
@@ -10,7 +10,8 @@ const { buildSmartError, builErrorFromResponse } = require('../responses/buildEr
|
|
|
10
10
|
const { RezoCookieJar, Cookie } = require('../cookies/cookie-jar.cjs');
|
|
11
11
|
const RezoFormData = require('../utils/form-data.cjs');
|
|
12
12
|
const { existsSync } = require("node:fs");
|
|
13
|
-
const { getDefaultConfig, prepareHTTPOptions, calculateRetryDelay } = require('../utils/http-config.cjs');
|
|
13
|
+
const { getDefaultConfig, prepareHTTPOptions, calculateRetryDelay, shouldRetry } = require('../utils/http-config.cjs');
|
|
14
|
+
const { handleRateLimitWait, shouldWaitOnStatus } = require('../utils/rate-limit-wait.cjs');
|
|
14
15
|
const { RezoHeaders } = require('../utils/headers.cjs');
|
|
15
16
|
const { StreamResponse } = require('../responses/stream.cjs');
|
|
16
17
|
const { DownloadResponse } = require('../responses/download.cjs');
|
|
@@ -2288,9 +2289,20 @@ async function executeRequest(options, defaultOptions, jar) {
|
|
|
2288
2289
|
}
|
|
2289
2290
|
}
|
|
2290
2291
|
const executor = new CurlExecutor;
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2292
|
+
const retryConfig = config.retry;
|
|
2293
|
+
let retryAttempt = 0;
|
|
2294
|
+
const ABSOLUTE_MAX_ATTEMPTS = 50;
|
|
2295
|
+
let totalAttempts = 0;
|
|
2296
|
+
while (true) {
|
|
2297
|
+
totalAttempts++;
|
|
2298
|
+
if (totalAttempts > ABSOLUTE_MAX_ATTEMPTS) {
|
|
2299
|
+
throw new RezoError(`Absolute maximum attempts (${ABSOLUTE_MAX_ATTEMPTS}) exceeded. This prevents infinite loops from retries and redirects.`, config, "ERR_MAX_ATTEMPTS", originalRequest);
|
|
2300
|
+
}
|
|
2301
|
+
try {
|
|
2302
|
+
const result = await executor.execute(config, originalRequest, streamResponse, downloadResponse, uploadResponse);
|
|
2303
|
+
if (streamResponse || downloadResponse || uploadResponse) {
|
|
2304
|
+
return result;
|
|
2305
|
+
}
|
|
2294
2306
|
const response = result;
|
|
2295
2307
|
if (proxyManager && selectedProxy) {
|
|
2296
2308
|
proxyManager.reportSuccess(selectedProxy);
|
|
@@ -2317,67 +2329,140 @@ async function executeRequest(options, defaultOptions, jar) {
|
|
|
2317
2329
|
}
|
|
2318
2330
|
}
|
|
2319
2331
|
debugLog.complete(config, response.finalUrl || requestUrl, config.redirectHistory?.length || 0, duration);
|
|
2320
|
-
|
|
2332
|
+
const _validateStatus = originalRequest.validateStatus ?? ((s) => s >= 200 && s < 300);
|
|
2333
|
+
if (originalRequest.validateStatus !== null && !_validateStatus(response.status)) {
|
|
2334
|
+
if (shouldWaitOnStatus(response.status, options.waitOnStatus)) {
|
|
2335
|
+
const rateLimitWaitAttempt = config._rateLimitWaitAttempt || 0;
|
|
2336
|
+
const waitResult = await handleRateLimitWait({
|
|
2337
|
+
status: response.status,
|
|
2338
|
+
headers: response.headers,
|
|
2339
|
+
data: response.data,
|
|
2340
|
+
url: requestUrl,
|
|
2341
|
+
method,
|
|
2342
|
+
config,
|
|
2343
|
+
options,
|
|
2344
|
+
currentWaitAttempt: rateLimitWaitAttempt
|
|
2345
|
+
});
|
|
2346
|
+
if (waitResult.shouldRetry) {
|
|
2347
|
+
config._rateLimitWaitAttempt = waitResult.waitAttempt;
|
|
2348
|
+
continue;
|
|
2349
|
+
}
|
|
2350
|
+
}
|
|
2321
2351
|
const httpError = builErrorFromResponse(`Request failed with status code ${response.status}`, response, config, originalRequest);
|
|
2322
|
-
if (
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
if (
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
config.errors = [];
|
|
2330
|
-
config.errors.push({
|
|
2331
|
-
attempt: config.retryAttempts,
|
|
2332
|
-
error: httpError,
|
|
2333
|
-
duration: perform.now()
|
|
2334
|
-
});
|
|
2335
|
-
perform.reset();
|
|
2336
|
-
const delay = calculateRetryDelay(config.retryAttempts, config.retry.retryDelay, config.retry.backoff, config.retry.maxDelay);
|
|
2337
|
-
debugLog.retry(config, config.retryAttempts, maxRetries, response.status, delay);
|
|
2338
|
-
if (config.hooks?.beforeRetry && config.hooks.beforeRetry.length > 0) {
|
|
2339
|
-
for (const hook of config.hooks.beforeRetry) {
|
|
2340
|
-
await hook(config, httpError, config.retryAttempts);
|
|
2341
|
-
}
|
|
2352
|
+
if (retryConfig) {
|
|
2353
|
+
retryAttempt++;
|
|
2354
|
+
if (retryConfig.condition) {
|
|
2355
|
+
const shouldContinue = await retryConfig.condition(httpError, retryAttempt);
|
|
2356
|
+
if (shouldContinue === false) {
|
|
2357
|
+
if (retryConfig.onRetryExhausted) {
|
|
2358
|
+
await retryConfig.onRetryExhausted(httpError, retryAttempt);
|
|
2342
2359
|
}
|
|
2343
|
-
|
|
2344
|
-
|
|
2360
|
+
throw httpError;
|
|
2361
|
+
}
|
|
2362
|
+
} else {
|
|
2363
|
+
const canRetry = shouldRetry(httpError, retryAttempt, method, retryConfig);
|
|
2364
|
+
if (!canRetry) {
|
|
2365
|
+
if (retryAttempt > retryConfig.maxRetries) {
|
|
2366
|
+
debugLog.maxRetries(config, retryConfig.maxRetries);
|
|
2367
|
+
if (retryConfig.onRetryExhausted) {
|
|
2368
|
+
await retryConfig.onRetryExhausted(httpError, retryAttempt);
|
|
2369
|
+
}
|
|
2345
2370
|
}
|
|
2346
|
-
|
|
2371
|
+
throw httpError;
|
|
2372
|
+
}
|
|
2373
|
+
}
|
|
2374
|
+
if (!config.errors)
|
|
2375
|
+
config.errors = [];
|
|
2376
|
+
config.errors.push({
|
|
2377
|
+
attempt: retryAttempt,
|
|
2378
|
+
error: httpError,
|
|
2379
|
+
duration: perform.now()
|
|
2380
|
+
});
|
|
2381
|
+
perform.reset();
|
|
2382
|
+
const currentDelay = calculateRetryDelay(retryAttempt, retryConfig.retryDelay, retryConfig.backoff, retryConfig.maxDelay);
|
|
2383
|
+
debugLog.retry(config, retryAttempt, retryConfig.maxRetries, response.status, currentDelay);
|
|
2384
|
+
if (retryConfig.onRetry) {
|
|
2385
|
+
const shouldProceed = await retryConfig.onRetry(httpError, retryAttempt, currentDelay);
|
|
2386
|
+
if (shouldProceed === false) {
|
|
2387
|
+
throw httpError;
|
|
2347
2388
|
}
|
|
2348
2389
|
}
|
|
2349
|
-
|
|
2390
|
+
if (config.hooks?.beforeRetry && config.hooks.beforeRetry.length > 0) {
|
|
2391
|
+
for (const hook of config.hooks.beforeRetry) {
|
|
2392
|
+
await hook(config, httpError, retryAttempt);
|
|
2393
|
+
}
|
|
2394
|
+
}
|
|
2395
|
+
if (currentDelay > 0) {
|
|
2396
|
+
await new Promise((resolve) => setTimeout(resolve, currentDelay));
|
|
2397
|
+
}
|
|
2398
|
+
config.retryAttempts++;
|
|
2399
|
+
continue;
|
|
2350
2400
|
}
|
|
2351
2401
|
throw httpError;
|
|
2352
2402
|
}
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2403
|
+
return result;
|
|
2404
|
+
} catch (error) {
|
|
2405
|
+
if (error instanceof RezoError) {
|
|
2406
|
+
if (retryConfig && !retryConfig.condition) {
|
|
2407
|
+
const errorCode = error.code ?? error.cause?.code;
|
|
2408
|
+
const isRetryableError = errorCode && shouldRetry(error, retryAttempt + 1, method, retryConfig);
|
|
2409
|
+
if (isRetryableError) {
|
|
2410
|
+
retryAttempt++;
|
|
2411
|
+
if (!config.errors)
|
|
2412
|
+
config.errors = [];
|
|
2413
|
+
config.errors.push({
|
|
2414
|
+
attempt: retryAttempt,
|
|
2415
|
+
error,
|
|
2416
|
+
duration: perform.now()
|
|
2417
|
+
});
|
|
2418
|
+
perform.reset();
|
|
2419
|
+
const currentDelay = calculateRetryDelay(retryAttempt, retryConfig.retryDelay, retryConfig.backoff, retryConfig.maxDelay);
|
|
2420
|
+
debugLog.retry(config, retryAttempt, retryConfig.maxRetries, 0, currentDelay);
|
|
2421
|
+
if (retryConfig.onRetry) {
|
|
2422
|
+
const shouldProceed = await retryConfig.onRetry(error, retryAttempt, currentDelay);
|
|
2423
|
+
if (shouldProceed === false)
|
|
2424
|
+
throw error;
|
|
2425
|
+
}
|
|
2426
|
+
if (config.hooks?.beforeRetry && config.hooks.beforeRetry.length > 0) {
|
|
2427
|
+
for (const hook of config.hooks.beforeRetry) {
|
|
2428
|
+
await hook(config, error, retryAttempt);
|
|
2429
|
+
}
|
|
2430
|
+
}
|
|
2431
|
+
if (currentDelay > 0) {
|
|
2432
|
+
await new Promise((resolve) => setTimeout(resolve, currentDelay));
|
|
2433
|
+
}
|
|
2434
|
+
config.retryAttempts++;
|
|
2435
|
+
continue;
|
|
2373
2436
|
}
|
|
2374
2437
|
}
|
|
2438
|
+
if (proxyManager && selectedProxy) {
|
|
2439
|
+
proxyManager.reportFailure(selectedProxy, error);
|
|
2440
|
+
if (proxyManager.config.retryWithNextProxy) {
|
|
2441
|
+
const maxProxyRetries = proxyManager.config.maxProxyRetries ?? 3;
|
|
2442
|
+
const proxyAttempt = (config._proxyRetryCount ?? 0) + 1;
|
|
2443
|
+
if (proxyAttempt <= maxProxyRetries) {
|
|
2444
|
+
config._proxyRetryCount = proxyAttempt;
|
|
2445
|
+
const retryUrl = typeof originalRequest.url === "string" ? originalRequest.url : originalRequest.url?.toString() || "";
|
|
2446
|
+
const nextProxy = proxyManager.next(retryUrl);
|
|
2447
|
+
if (nextProxy) {
|
|
2448
|
+
originalRequest.proxy = {
|
|
2449
|
+
protocol: nextProxy.protocol,
|
|
2450
|
+
host: nextProxy.host,
|
|
2451
|
+
port: nextProxy.port,
|
|
2452
|
+
auth: nextProxy.auth
|
|
2453
|
+
};
|
|
2454
|
+
continue;
|
|
2455
|
+
}
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
2458
|
+
}
|
|
2459
|
+
throw error;
|
|
2375
2460
|
}
|
|
2461
|
+
if (proxyManager && selectedProxy) {
|
|
2462
|
+
proxyManager.reportFailure(selectedProxy, error);
|
|
2463
|
+
}
|
|
2464
|
+
throw buildSmartError(config, originalRequest, error);
|
|
2376
2465
|
}
|
|
2377
|
-
if (error instanceof RezoError) {
|
|
2378
|
-
throw error;
|
|
2379
|
-
}
|
|
2380
|
-
throw buildSmartError(config, originalRequest, error);
|
|
2381
2466
|
}
|
|
2382
2467
|
}
|
|
2383
2468
|
|
package/dist/adapters/curl.js
CHANGED
|
@@ -10,7 +10,8 @@ import { buildSmartError, builErrorFromResponse } from '../responses/buildError.
|
|
|
10
10
|
import { RezoCookieJar, Cookie } from '../cookies/cookie-jar.js';
|
|
11
11
|
import RezoFormData from '../utils/form-data.js';
|
|
12
12
|
import { existsSync } from "node:fs";
|
|
13
|
-
import { getDefaultConfig, prepareHTTPOptions, calculateRetryDelay } from '../utils/http-config.js';
|
|
13
|
+
import { getDefaultConfig, prepareHTTPOptions, calculateRetryDelay, shouldRetry } from '../utils/http-config.js';
|
|
14
|
+
import { handleRateLimitWait, shouldWaitOnStatus } from '../utils/rate-limit-wait.js';
|
|
14
15
|
import { RezoHeaders } from '../utils/headers.js';
|
|
15
16
|
import { StreamResponse } from '../responses/stream.js';
|
|
16
17
|
import { DownloadResponse } from '../responses/download.js';
|
|
@@ -2288,9 +2289,20 @@ export async function executeRequest(options, defaultOptions, jar) {
|
|
|
2288
2289
|
}
|
|
2289
2290
|
}
|
|
2290
2291
|
const executor = new CurlExecutor;
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2292
|
+
const retryConfig = config.retry;
|
|
2293
|
+
let retryAttempt = 0;
|
|
2294
|
+
const ABSOLUTE_MAX_ATTEMPTS = 50;
|
|
2295
|
+
let totalAttempts = 0;
|
|
2296
|
+
while (true) {
|
|
2297
|
+
totalAttempts++;
|
|
2298
|
+
if (totalAttempts > ABSOLUTE_MAX_ATTEMPTS) {
|
|
2299
|
+
throw new RezoError(`Absolute maximum attempts (${ABSOLUTE_MAX_ATTEMPTS}) exceeded. This prevents infinite loops from retries and redirects.`, config, "ERR_MAX_ATTEMPTS", originalRequest);
|
|
2300
|
+
}
|
|
2301
|
+
try {
|
|
2302
|
+
const result = await executor.execute(config, originalRequest, streamResponse, downloadResponse, uploadResponse);
|
|
2303
|
+
if (streamResponse || downloadResponse || uploadResponse) {
|
|
2304
|
+
return result;
|
|
2305
|
+
}
|
|
2294
2306
|
const response = result;
|
|
2295
2307
|
if (proxyManager && selectedProxy) {
|
|
2296
2308
|
proxyManager.reportSuccess(selectedProxy);
|
|
@@ -2317,67 +2329,140 @@ export async function executeRequest(options, defaultOptions, jar) {
|
|
|
2317
2329
|
}
|
|
2318
2330
|
}
|
|
2319
2331
|
debugLog.complete(config, response.finalUrl || requestUrl, config.redirectHistory?.length || 0, duration);
|
|
2320
|
-
|
|
2332
|
+
const _validateStatus = originalRequest.validateStatus ?? ((s) => s >= 200 && s < 300);
|
|
2333
|
+
if (originalRequest.validateStatus !== null && !_validateStatus(response.status)) {
|
|
2334
|
+
if (shouldWaitOnStatus(response.status, options.waitOnStatus)) {
|
|
2335
|
+
const rateLimitWaitAttempt = config._rateLimitWaitAttempt || 0;
|
|
2336
|
+
const waitResult = await handleRateLimitWait({
|
|
2337
|
+
status: response.status,
|
|
2338
|
+
headers: response.headers,
|
|
2339
|
+
data: response.data,
|
|
2340
|
+
url: requestUrl,
|
|
2341
|
+
method,
|
|
2342
|
+
config,
|
|
2343
|
+
options,
|
|
2344
|
+
currentWaitAttempt: rateLimitWaitAttempt
|
|
2345
|
+
});
|
|
2346
|
+
if (waitResult.shouldRetry) {
|
|
2347
|
+
config._rateLimitWaitAttempt = waitResult.waitAttempt;
|
|
2348
|
+
continue;
|
|
2349
|
+
}
|
|
2350
|
+
}
|
|
2321
2351
|
const httpError = builErrorFromResponse(`Request failed with status code ${response.status}`, response, config, originalRequest);
|
|
2322
|
-
if (
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
if (
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
config.errors = [];
|
|
2330
|
-
config.errors.push({
|
|
2331
|
-
attempt: config.retryAttempts,
|
|
2332
|
-
error: httpError,
|
|
2333
|
-
duration: perform.now()
|
|
2334
|
-
});
|
|
2335
|
-
perform.reset();
|
|
2336
|
-
const delay = calculateRetryDelay(config.retryAttempts, config.retry.retryDelay, config.retry.backoff, config.retry.maxDelay);
|
|
2337
|
-
debugLog.retry(config, config.retryAttempts, maxRetries, response.status, delay);
|
|
2338
|
-
if (config.hooks?.beforeRetry && config.hooks.beforeRetry.length > 0) {
|
|
2339
|
-
for (const hook of config.hooks.beforeRetry) {
|
|
2340
|
-
await hook(config, httpError, config.retryAttempts);
|
|
2341
|
-
}
|
|
2352
|
+
if (retryConfig) {
|
|
2353
|
+
retryAttempt++;
|
|
2354
|
+
if (retryConfig.condition) {
|
|
2355
|
+
const shouldContinue = await retryConfig.condition(httpError, retryAttempt);
|
|
2356
|
+
if (shouldContinue === false) {
|
|
2357
|
+
if (retryConfig.onRetryExhausted) {
|
|
2358
|
+
await retryConfig.onRetryExhausted(httpError, retryAttempt);
|
|
2342
2359
|
}
|
|
2343
|
-
|
|
2344
|
-
|
|
2360
|
+
throw httpError;
|
|
2361
|
+
}
|
|
2362
|
+
} else {
|
|
2363
|
+
const canRetry = shouldRetry(httpError, retryAttempt, method, retryConfig);
|
|
2364
|
+
if (!canRetry) {
|
|
2365
|
+
if (retryAttempt > retryConfig.maxRetries) {
|
|
2366
|
+
debugLog.maxRetries(config, retryConfig.maxRetries);
|
|
2367
|
+
if (retryConfig.onRetryExhausted) {
|
|
2368
|
+
await retryConfig.onRetryExhausted(httpError, retryAttempt);
|
|
2369
|
+
}
|
|
2345
2370
|
}
|
|
2346
|
-
|
|
2371
|
+
throw httpError;
|
|
2372
|
+
}
|
|
2373
|
+
}
|
|
2374
|
+
if (!config.errors)
|
|
2375
|
+
config.errors = [];
|
|
2376
|
+
config.errors.push({
|
|
2377
|
+
attempt: retryAttempt,
|
|
2378
|
+
error: httpError,
|
|
2379
|
+
duration: perform.now()
|
|
2380
|
+
});
|
|
2381
|
+
perform.reset();
|
|
2382
|
+
const currentDelay = calculateRetryDelay(retryAttempt, retryConfig.retryDelay, retryConfig.backoff, retryConfig.maxDelay);
|
|
2383
|
+
debugLog.retry(config, retryAttempt, retryConfig.maxRetries, response.status, currentDelay);
|
|
2384
|
+
if (retryConfig.onRetry) {
|
|
2385
|
+
const shouldProceed = await retryConfig.onRetry(httpError, retryAttempt, currentDelay);
|
|
2386
|
+
if (shouldProceed === false) {
|
|
2387
|
+
throw httpError;
|
|
2347
2388
|
}
|
|
2348
2389
|
}
|
|
2349
|
-
|
|
2390
|
+
if (config.hooks?.beforeRetry && config.hooks.beforeRetry.length > 0) {
|
|
2391
|
+
for (const hook of config.hooks.beforeRetry) {
|
|
2392
|
+
await hook(config, httpError, retryAttempt);
|
|
2393
|
+
}
|
|
2394
|
+
}
|
|
2395
|
+
if (currentDelay > 0) {
|
|
2396
|
+
await new Promise((resolve) => setTimeout(resolve, currentDelay));
|
|
2397
|
+
}
|
|
2398
|
+
config.retryAttempts++;
|
|
2399
|
+
continue;
|
|
2350
2400
|
}
|
|
2351
2401
|
throw httpError;
|
|
2352
2402
|
}
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2403
|
+
return result;
|
|
2404
|
+
} catch (error) {
|
|
2405
|
+
if (error instanceof RezoError) {
|
|
2406
|
+
if (retryConfig && !retryConfig.condition) {
|
|
2407
|
+
const errorCode = error.code ?? error.cause?.code;
|
|
2408
|
+
const isRetryableError = errorCode && shouldRetry(error, retryAttempt + 1, method, retryConfig);
|
|
2409
|
+
if (isRetryableError) {
|
|
2410
|
+
retryAttempt++;
|
|
2411
|
+
if (!config.errors)
|
|
2412
|
+
config.errors = [];
|
|
2413
|
+
config.errors.push({
|
|
2414
|
+
attempt: retryAttempt,
|
|
2415
|
+
error,
|
|
2416
|
+
duration: perform.now()
|
|
2417
|
+
});
|
|
2418
|
+
perform.reset();
|
|
2419
|
+
const currentDelay = calculateRetryDelay(retryAttempt, retryConfig.retryDelay, retryConfig.backoff, retryConfig.maxDelay);
|
|
2420
|
+
debugLog.retry(config, retryAttempt, retryConfig.maxRetries, 0, currentDelay);
|
|
2421
|
+
if (retryConfig.onRetry) {
|
|
2422
|
+
const shouldProceed = await retryConfig.onRetry(error, retryAttempt, currentDelay);
|
|
2423
|
+
if (shouldProceed === false)
|
|
2424
|
+
throw error;
|
|
2425
|
+
}
|
|
2426
|
+
if (config.hooks?.beforeRetry && config.hooks.beforeRetry.length > 0) {
|
|
2427
|
+
for (const hook of config.hooks.beforeRetry) {
|
|
2428
|
+
await hook(config, error, retryAttempt);
|
|
2429
|
+
}
|
|
2430
|
+
}
|
|
2431
|
+
if (currentDelay > 0) {
|
|
2432
|
+
await new Promise((resolve) => setTimeout(resolve, currentDelay));
|
|
2433
|
+
}
|
|
2434
|
+
config.retryAttempts++;
|
|
2435
|
+
continue;
|
|
2373
2436
|
}
|
|
2374
2437
|
}
|
|
2438
|
+
if (proxyManager && selectedProxy) {
|
|
2439
|
+
proxyManager.reportFailure(selectedProxy, error);
|
|
2440
|
+
if (proxyManager.config.retryWithNextProxy) {
|
|
2441
|
+
const maxProxyRetries = proxyManager.config.maxProxyRetries ?? 3;
|
|
2442
|
+
const proxyAttempt = (config._proxyRetryCount ?? 0) + 1;
|
|
2443
|
+
if (proxyAttempt <= maxProxyRetries) {
|
|
2444
|
+
config._proxyRetryCount = proxyAttempt;
|
|
2445
|
+
const retryUrl = typeof originalRequest.url === "string" ? originalRequest.url : originalRequest.url?.toString() || "";
|
|
2446
|
+
const nextProxy = proxyManager.next(retryUrl);
|
|
2447
|
+
if (nextProxy) {
|
|
2448
|
+
originalRequest.proxy = {
|
|
2449
|
+
protocol: nextProxy.protocol,
|
|
2450
|
+
host: nextProxy.host,
|
|
2451
|
+
port: nextProxy.port,
|
|
2452
|
+
auth: nextProxy.auth
|
|
2453
|
+
};
|
|
2454
|
+
continue;
|
|
2455
|
+
}
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
2458
|
+
}
|
|
2459
|
+
throw error;
|
|
2375
2460
|
}
|
|
2461
|
+
if (proxyManager && selectedProxy) {
|
|
2462
|
+
proxyManager.reportFailure(selectedProxy, error);
|
|
2463
|
+
}
|
|
2464
|
+
throw buildSmartError(config, originalRequest, error);
|
|
2376
2465
|
}
|
|
2377
|
-
if (error instanceof RezoError) {
|
|
2378
|
-
throw error;
|
|
2379
|
-
}
|
|
2380
|
-
throw buildSmartError(config, originalRequest, error);
|
|
2381
2466
|
}
|
|
2382
2467
|
}
|
|
2383
2468
|
|
|
@@ -2921,6 +2921,23 @@ export interface RezoDefaultOptions {
|
|
|
2921
2921
|
* ```
|
|
2922
2922
|
*/
|
|
2923
2923
|
proxyManager?: ProxyManager | ProxyManagerConfig;
|
|
2924
|
+
/**
|
|
2925
|
+
* Determines whether a given HTTP status code should be treated as successful.
|
|
2926
|
+
* When a status code fails validation, the request throws an error.
|
|
2927
|
+
*
|
|
2928
|
+
* @default (status) => status >= 200 && status < 300
|
|
2929
|
+
*/
|
|
2930
|
+
validateStatus?: ((status: number) => boolean) | null;
|
|
2931
|
+
/**
|
|
2932
|
+
* Custom function to serialize URL query parameters.
|
|
2933
|
+
* Replaces the default serialization logic.
|
|
2934
|
+
*/
|
|
2935
|
+
paramsSerializer?: (params: Record<string, any>) => string;
|
|
2936
|
+
/**
|
|
2937
|
+
* Custom DNS lookup function for hostname resolution.
|
|
2938
|
+
* Replaces the default `dns.lookup` used by Node.js.
|
|
2939
|
+
*/
|
|
2940
|
+
dnsLookup?: RezoHttpRequest["dnsLookup"];
|
|
2924
2941
|
/** Browser fingerprint stealth configuration (instance-level only) */
|
|
2925
2942
|
stealth?: RezoStealth;
|
|
2926
2943
|
}
|
|
@@ -3302,6 +3319,16 @@ export interface RezoConfig {
|
|
|
3302
3319
|
onRedirect?: RezoRequestConfig["beforeRedirect"];
|
|
3303
3320
|
/** Character encoding for request body and response data */
|
|
3304
3321
|
encoding?: BufferEncoding;
|
|
3322
|
+
/**
|
|
3323
|
+
* Determines whether a given HTTP status code should be treated as successful.
|
|
3324
|
+
* Used by adapters to decide if a response is an error.
|
|
3325
|
+
* @default (status) => status >= 200 && status < 300
|
|
3326
|
+
*/
|
|
3327
|
+
validateStatus?: ((status: number) => boolean) | null;
|
|
3328
|
+
/**
|
|
3329
|
+
* Custom DNS lookup function for hostname resolution.
|
|
3330
|
+
*/
|
|
3331
|
+
dnsLookup?: (hostname: string, options: any, callback: (err: Error | null, address: string, family: number) => void) => void;
|
|
3305
3332
|
/**
|
|
3306
3333
|
* Whether to use cookies for the request
|
|
3307
3334
|
*/
|
|
@@ -4117,6 +4144,60 @@ export interface RezoRequestConfig<D = any> {
|
|
|
4117
4144
|
};
|
|
4118
4145
|
/** Character encoding for request body and response data */
|
|
4119
4146
|
encoding?: BufferEncoding;
|
|
4147
|
+
/**
|
|
4148
|
+
* Determines whether a given HTTP status code should be treated as a successful response.
|
|
4149
|
+
* When a status code fails validation, the request will throw an error.
|
|
4150
|
+
*
|
|
4151
|
+
* @param status - The HTTP response status code
|
|
4152
|
+
* @returns true if the status code should be considered successful
|
|
4153
|
+
*
|
|
4154
|
+
* @default (status) => status >= 200 && status < 300
|
|
4155
|
+
*
|
|
4156
|
+
* @example
|
|
4157
|
+
* ```typescript
|
|
4158
|
+
* // Accept all 2xx and 3xx as success
|
|
4159
|
+
* validateStatus: (status) => status >= 200 && status < 400
|
|
4160
|
+
*
|
|
4161
|
+
* // Never throw on any status code
|
|
4162
|
+
* validateStatus: () => true
|
|
4163
|
+
*
|
|
4164
|
+
* // Only accept 200
|
|
4165
|
+
* validateStatus: (status) => status === 200
|
|
4166
|
+
* ```
|
|
4167
|
+
*/
|
|
4168
|
+
validateStatus?: ((status: number) => boolean) | null;
|
|
4169
|
+
/**
|
|
4170
|
+
* Custom function to serialize URL query parameters.
|
|
4171
|
+
* When provided, this replaces the default serialization logic.
|
|
4172
|
+
*
|
|
4173
|
+
* @param params - The params object to serialize
|
|
4174
|
+
* @returns The serialized query string (without leading '?')
|
|
4175
|
+
*
|
|
4176
|
+
* @example
|
|
4177
|
+
* ```typescript
|
|
4178
|
+
* // Custom array serialization
|
|
4179
|
+
* paramsSerializer: (params) => qs.stringify(params, { arrayFormat: 'brackets' })
|
|
4180
|
+
*
|
|
4181
|
+
* // Simple key=value pairs
|
|
4182
|
+
* paramsSerializer: (params) =>
|
|
4183
|
+
* Object.entries(params).map(([k, v]) => `${k}=${v}`).join('&')
|
|
4184
|
+
* ```
|
|
4185
|
+
*/
|
|
4186
|
+
paramsSerializer?: (params: Record<string, any>) => string;
|
|
4187
|
+
/**
|
|
4188
|
+
* Custom DNS lookup function for hostname resolution.
|
|
4189
|
+
* Replaces the default `dns.lookup` used by Node.js for this request.
|
|
4190
|
+
*
|
|
4191
|
+
* @example
|
|
4192
|
+
* ```typescript
|
|
4193
|
+
* import { lookup } from 'node:dns/promises';
|
|
4194
|
+
* dnsLookup: (hostname, options, callback) => {
|
|
4195
|
+
* // Custom DNS resolution logic
|
|
4196
|
+
* lookup(hostname).then(result => callback(null, result.address, result.family));
|
|
4197
|
+
* }
|
|
4198
|
+
* ```
|
|
4199
|
+
*/
|
|
4200
|
+
dnsLookup?: (hostname: string, options: any, callback: (err: Error | null, address: string, family: number) => void) => void;
|
|
4120
4201
|
/**
|
|
4121
4202
|
* Request lifecycle hooks for intercepting and modifying request/response behavior.
|
|
4122
4203
|
* Optional hooks that will be merged with default hooks during request processing.
|
|
@@ -5591,7 +5672,7 @@ export interface RezoInstance extends Rezo, RezoCallable {
|
|
|
5591
5672
|
*
|
|
5592
5673
|
* IMPORTANT: Update these values when bumping package version.
|
|
5593
5674
|
*/
|
|
5594
|
-
export declare const VERSION = "1.0.
|
|
5675
|
+
export declare const VERSION = "1.0.108";
|
|
5595
5676
|
/**
|
|
5596
5677
|
* cURL Options Configuration
|
|
5597
5678
|
*
|
|
@@ -2921,6 +2921,23 @@ export interface RezoDefaultOptions {
|
|
|
2921
2921
|
* ```
|
|
2922
2922
|
*/
|
|
2923
2923
|
proxyManager?: ProxyManager | ProxyManagerConfig;
|
|
2924
|
+
/**
|
|
2925
|
+
* Determines whether a given HTTP status code should be treated as successful.
|
|
2926
|
+
* When a status code fails validation, the request throws an error.
|
|
2927
|
+
*
|
|
2928
|
+
* @default (status) => status >= 200 && status < 300
|
|
2929
|
+
*/
|
|
2930
|
+
validateStatus?: ((status: number) => boolean) | null;
|
|
2931
|
+
/**
|
|
2932
|
+
* Custom function to serialize URL query parameters.
|
|
2933
|
+
* Replaces the default serialization logic.
|
|
2934
|
+
*/
|
|
2935
|
+
paramsSerializer?: (params: Record<string, any>) => string;
|
|
2936
|
+
/**
|
|
2937
|
+
* Custom DNS lookup function for hostname resolution.
|
|
2938
|
+
* Replaces the default `dns.lookup` used by Node.js.
|
|
2939
|
+
*/
|
|
2940
|
+
dnsLookup?: RezoHttpRequest["dnsLookup"];
|
|
2924
2941
|
/** Browser fingerprint stealth configuration (instance-level only) */
|
|
2925
2942
|
stealth?: RezoStealth;
|
|
2926
2943
|
}
|
|
@@ -3302,6 +3319,16 @@ export interface RezoConfig {
|
|
|
3302
3319
|
onRedirect?: RezoRequestConfig["beforeRedirect"];
|
|
3303
3320
|
/** Character encoding for request body and response data */
|
|
3304
3321
|
encoding?: BufferEncoding;
|
|
3322
|
+
/**
|
|
3323
|
+
* Determines whether a given HTTP status code should be treated as successful.
|
|
3324
|
+
* Used by adapters to decide if a response is an error.
|
|
3325
|
+
* @default (status) => status >= 200 && status < 300
|
|
3326
|
+
*/
|
|
3327
|
+
validateStatus?: ((status: number) => boolean) | null;
|
|
3328
|
+
/**
|
|
3329
|
+
* Custom DNS lookup function for hostname resolution.
|
|
3330
|
+
*/
|
|
3331
|
+
dnsLookup?: (hostname: string, options: any, callback: (err: Error | null, address: string, family: number) => void) => void;
|
|
3305
3332
|
/**
|
|
3306
3333
|
* Whether to use cookies for the request
|
|
3307
3334
|
*/
|
|
@@ -4117,6 +4144,60 @@ export interface RezoRequestConfig<D = any> {
|
|
|
4117
4144
|
};
|
|
4118
4145
|
/** Character encoding for request body and response data */
|
|
4119
4146
|
encoding?: BufferEncoding;
|
|
4147
|
+
/**
|
|
4148
|
+
* Determines whether a given HTTP status code should be treated as a successful response.
|
|
4149
|
+
* When a status code fails validation, the request will throw an error.
|
|
4150
|
+
*
|
|
4151
|
+
* @param status - The HTTP response status code
|
|
4152
|
+
* @returns true if the status code should be considered successful
|
|
4153
|
+
*
|
|
4154
|
+
* @default (status) => status >= 200 && status < 300
|
|
4155
|
+
*
|
|
4156
|
+
* @example
|
|
4157
|
+
* ```typescript
|
|
4158
|
+
* // Accept all 2xx and 3xx as success
|
|
4159
|
+
* validateStatus: (status) => status >= 200 && status < 400
|
|
4160
|
+
*
|
|
4161
|
+
* // Never throw on any status code
|
|
4162
|
+
* validateStatus: () => true
|
|
4163
|
+
*
|
|
4164
|
+
* // Only accept 200
|
|
4165
|
+
* validateStatus: (status) => status === 200
|
|
4166
|
+
* ```
|
|
4167
|
+
*/
|
|
4168
|
+
validateStatus?: ((status: number) => boolean) | null;
|
|
4169
|
+
/**
|
|
4170
|
+
* Custom function to serialize URL query parameters.
|
|
4171
|
+
* When provided, this replaces the default serialization logic.
|
|
4172
|
+
*
|
|
4173
|
+
* @param params - The params object to serialize
|
|
4174
|
+
* @returns The serialized query string (without leading '?')
|
|
4175
|
+
*
|
|
4176
|
+
* @example
|
|
4177
|
+
* ```typescript
|
|
4178
|
+
* // Custom array serialization
|
|
4179
|
+
* paramsSerializer: (params) => qs.stringify(params, { arrayFormat: 'brackets' })
|
|
4180
|
+
*
|
|
4181
|
+
* // Simple key=value pairs
|
|
4182
|
+
* paramsSerializer: (params) =>
|
|
4183
|
+
* Object.entries(params).map(([k, v]) => `${k}=${v}`).join('&')
|
|
4184
|
+
* ```
|
|
4185
|
+
*/
|
|
4186
|
+
paramsSerializer?: (params: Record<string, any>) => string;
|
|
4187
|
+
/**
|
|
4188
|
+
* Custom DNS lookup function for hostname resolution.
|
|
4189
|
+
* Replaces the default `dns.lookup` used by Node.js for this request.
|
|
4190
|
+
*
|
|
4191
|
+
* @example
|
|
4192
|
+
* ```typescript
|
|
4193
|
+
* import { lookup } from 'node:dns/promises';
|
|
4194
|
+
* dnsLookup: (hostname, options, callback) => {
|
|
4195
|
+
* // Custom DNS resolution logic
|
|
4196
|
+
* lookup(hostname).then(result => callback(null, result.address, result.family));
|
|
4197
|
+
* }
|
|
4198
|
+
* ```
|
|
4199
|
+
*/
|
|
4200
|
+
dnsLookup?: (hostname: string, options: any, callback: (err: Error | null, address: string, family: number) => void) => void;
|
|
4120
4201
|
/**
|
|
4121
4202
|
* Request lifecycle hooks for intercepting and modifying request/response behavior.
|
|
4122
4203
|
* Optional hooks that will be merged with default hooks during request processing.
|
|
@@ -5591,7 +5672,7 @@ export interface RezoInstance extends Rezo, RezoCallable {
|
|
|
5591
5672
|
*
|
|
5592
5673
|
* IMPORTANT: Update these values when bumping package version.
|
|
5593
5674
|
*/
|
|
5594
|
-
export declare const VERSION = "1.0.
|
|
5675
|
+
export declare const VERSION = "1.0.108";
|
|
5595
5676
|
export declare const isRezoError: typeof RezoError.isRezoError;
|
|
5596
5677
|
export declare const Cancel: typeof RezoError;
|
|
5597
5678
|
export declare const CancelToken: {
|