rezo 1.0.41 → 1.0.43
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 +143 -32
- package/dist/adapters/curl.js +143 -32
- package/dist/adapters/entries/curl.d.ts +65 -0
- package/dist/adapters/entries/fetch.d.ts +65 -0
- package/dist/adapters/entries/http.d.ts +65 -0
- package/dist/adapters/entries/http2.d.ts +65 -0
- package/dist/adapters/entries/react-native.d.ts +65 -0
- package/dist/adapters/entries/xhr.d.ts +65 -0
- package/dist/adapters/fetch.cjs +98 -12
- package/dist/adapters/fetch.js +98 -12
- package/dist/adapters/http.cjs +26 -14
- package/dist/adapters/http.js +26 -14
- package/dist/adapters/http2.cjs +756 -227
- package/dist/adapters/http2.js +756 -227
- package/dist/adapters/index.cjs +6 -6
- package/dist/adapters/xhr.cjs +94 -2
- package/dist/adapters/xhr.js +94 -2
- package/dist/cache/dns-cache.cjs +5 -3
- package/dist/cache/dns-cache.js +5 -3
- package/dist/cache/file-cacher.cjs +7 -1
- package/dist/cache/file-cacher.js +7 -1
- package/dist/cache/index.cjs +15 -13
- package/dist/cache/index.js +1 -0
- package/dist/cache/navigation-history.cjs +298 -0
- package/dist/cache/navigation-history.js +296 -0
- package/dist/cache/url-store.cjs +7 -1
- package/dist/cache/url-store.js +7 -1
- package/dist/core/rezo.cjs +7 -0
- package/dist/core/rezo.js +7 -0
- package/dist/crawler.d.ts +196 -11
- package/dist/entries/crawler.cjs +5 -5
- package/dist/index.cjs +27 -24
- package/dist/index.d.ts +73 -0
- package/dist/index.js +1 -0
- package/dist/internal/agents/base.cjs +113 -0
- package/dist/internal/agents/base.js +110 -0
- package/dist/internal/agents/http-proxy.cjs +89 -0
- package/dist/internal/agents/http-proxy.js +86 -0
- package/dist/internal/agents/https-proxy.cjs +176 -0
- package/dist/internal/agents/https-proxy.js +173 -0
- package/dist/internal/agents/index.cjs +10 -0
- package/dist/internal/agents/index.js +5 -0
- package/dist/internal/agents/socks-client.cjs +571 -0
- package/dist/internal/agents/socks-client.js +567 -0
- package/dist/internal/agents/socks-proxy.cjs +75 -0
- package/dist/internal/agents/socks-proxy.js +72 -0
- package/dist/platform/browser.d.ts +65 -0
- package/dist/platform/bun.d.ts +65 -0
- package/dist/platform/deno.d.ts +65 -0
- package/dist/platform/node.d.ts +65 -0
- package/dist/platform/react-native.d.ts +65 -0
- package/dist/platform/worker.d.ts +65 -0
- package/dist/plugin/crawler-options.cjs +1 -1
- package/dist/plugin/crawler-options.js +1 -1
- package/dist/plugin/crawler.cjs +192 -1
- package/dist/plugin/crawler.js +192 -1
- package/dist/plugin/index.cjs +36 -36
- package/dist/proxy/index.cjs +18 -16
- package/dist/proxy/index.js +17 -12
- package/dist/queue/index.cjs +8 -8
- package/dist/responses/buildError.cjs +11 -2
- package/dist/responses/buildError.js +11 -2
- package/dist/responses/universal/index.cjs +11 -11
- package/dist/utils/agent-pool.cjs +1 -17
- package/dist/utils/agent-pool.js +1 -17
- package/dist/utils/curl.cjs +317 -0
- package/dist/utils/curl.js +314 -0
- package/package.json +1 -1
|
@@ -4355,6 +4355,71 @@ export declare class Rezo {
|
|
|
4355
4355
|
* @see {@link cookieJar} - Access the underlying RezoCookieJar for more control
|
|
4356
4356
|
*/
|
|
4357
4357
|
clearCookies(): void;
|
|
4358
|
+
/**
|
|
4359
|
+
* Convert a Rezo request configuration to a cURL command string.
|
|
4360
|
+
*
|
|
4361
|
+
* Generates a valid cURL command that can be executed in a terminal to
|
|
4362
|
+
* reproduce the same HTTP request. Useful for:
|
|
4363
|
+
* - Debugging and sharing requests
|
|
4364
|
+
* - Documentation and examples
|
|
4365
|
+
* - Testing requests outside of Node.js
|
|
4366
|
+
* - Exporting requests to other tools
|
|
4367
|
+
*
|
|
4368
|
+
* @param config - Request configuration object
|
|
4369
|
+
* @returns A cURL command string
|
|
4370
|
+
*
|
|
4371
|
+
* @example
|
|
4372
|
+
* ```typescript
|
|
4373
|
+
* const curl = Rezo.toCurl({
|
|
4374
|
+
* url: 'https://api.example.com/users',
|
|
4375
|
+
* method: 'POST',
|
|
4376
|
+
* headers: { 'Content-Type': 'application/json' },
|
|
4377
|
+
* body: { name: 'John', email: 'john@example.com' }
|
|
4378
|
+
* });
|
|
4379
|
+
* // Output: curl -X POST -H 'content-type: application/json' --data-raw '{"name":"John","email":"john@example.com"}' -L --compressed 'https://api.example.com/users'
|
|
4380
|
+
* ```
|
|
4381
|
+
*/
|
|
4382
|
+
static toCurl(config: RezoRequestConfig | RezoRequestOptions): string;
|
|
4383
|
+
/**
|
|
4384
|
+
* Parse a cURL command string into a Rezo request configuration.
|
|
4385
|
+
*
|
|
4386
|
+
* Converts a cURL command into a configuration object that can be
|
|
4387
|
+
* passed directly to Rezo request methods. Useful for:
|
|
4388
|
+
* - Importing requests from browser DevTools
|
|
4389
|
+
* - Converting curl examples from API documentation
|
|
4390
|
+
* - Migrating scripts from curl to Rezo
|
|
4391
|
+
*
|
|
4392
|
+
* Supports common cURL options:
|
|
4393
|
+
* - `-X, --request` - HTTP method
|
|
4394
|
+
* - `-H, --header` - Request headers
|
|
4395
|
+
* - `-d, --data, --data-raw, --data-binary` - Request body
|
|
4396
|
+
* - `-u, --user` - Basic authentication
|
|
4397
|
+
* - `-x, --proxy` - Proxy configuration
|
|
4398
|
+
* - `--socks5, --socks4` - SOCKS proxy
|
|
4399
|
+
* - `-L, --location` - Follow redirects
|
|
4400
|
+
* - `--max-redirs` - Maximum redirects
|
|
4401
|
+
* - `--max-time` - Request timeout
|
|
4402
|
+
* - `-k, --insecure` - Skip TLS verification
|
|
4403
|
+
* - `-A, --user-agent` - User agent header
|
|
4404
|
+
*
|
|
4405
|
+
* @param curlCommand - A cURL command string
|
|
4406
|
+
* @returns A request configuration object
|
|
4407
|
+
*
|
|
4408
|
+
* @example
|
|
4409
|
+
* ```typescript
|
|
4410
|
+
* // From browser DevTools "Copy as cURL"
|
|
4411
|
+
* const config = Rezo.fromCurl(`
|
|
4412
|
+
* curl 'https://api.example.com/data' \\
|
|
4413
|
+
* -H 'Authorization: Bearer token123' \\
|
|
4414
|
+
* -H 'Content-Type: application/json'
|
|
4415
|
+
* `);
|
|
4416
|
+
*
|
|
4417
|
+
* // Use with Rezo
|
|
4418
|
+
* const rezo = new Rezo();
|
|
4419
|
+
* const response = await rezo.request(config);
|
|
4420
|
+
* ```
|
|
4421
|
+
*/
|
|
4422
|
+
static fromCurl(curlCommand: string): RezoRequestOptions;
|
|
4358
4423
|
}
|
|
4359
4424
|
/**
|
|
4360
4425
|
* Extended Rezo instance with Axios-compatible static helpers.
|
|
@@ -4355,6 +4355,71 @@ export declare class Rezo {
|
|
|
4355
4355
|
* @see {@link cookieJar} - Access the underlying RezoCookieJar for more control
|
|
4356
4356
|
*/
|
|
4357
4357
|
clearCookies(): void;
|
|
4358
|
+
/**
|
|
4359
|
+
* Convert a Rezo request configuration to a cURL command string.
|
|
4360
|
+
*
|
|
4361
|
+
* Generates a valid cURL command that can be executed in a terminal to
|
|
4362
|
+
* reproduce the same HTTP request. Useful for:
|
|
4363
|
+
* - Debugging and sharing requests
|
|
4364
|
+
* - Documentation and examples
|
|
4365
|
+
* - Testing requests outside of Node.js
|
|
4366
|
+
* - Exporting requests to other tools
|
|
4367
|
+
*
|
|
4368
|
+
* @param config - Request configuration object
|
|
4369
|
+
* @returns A cURL command string
|
|
4370
|
+
*
|
|
4371
|
+
* @example
|
|
4372
|
+
* ```typescript
|
|
4373
|
+
* const curl = Rezo.toCurl({
|
|
4374
|
+
* url: 'https://api.example.com/users',
|
|
4375
|
+
* method: 'POST',
|
|
4376
|
+
* headers: { 'Content-Type': 'application/json' },
|
|
4377
|
+
* body: { name: 'John', email: 'john@example.com' }
|
|
4378
|
+
* });
|
|
4379
|
+
* // Output: curl -X POST -H 'content-type: application/json' --data-raw '{"name":"John","email":"john@example.com"}' -L --compressed 'https://api.example.com/users'
|
|
4380
|
+
* ```
|
|
4381
|
+
*/
|
|
4382
|
+
static toCurl(config: RezoRequestConfig | RezoRequestOptions): string;
|
|
4383
|
+
/**
|
|
4384
|
+
* Parse a cURL command string into a Rezo request configuration.
|
|
4385
|
+
*
|
|
4386
|
+
* Converts a cURL command into a configuration object that can be
|
|
4387
|
+
* passed directly to Rezo request methods. Useful for:
|
|
4388
|
+
* - Importing requests from browser DevTools
|
|
4389
|
+
* - Converting curl examples from API documentation
|
|
4390
|
+
* - Migrating scripts from curl to Rezo
|
|
4391
|
+
*
|
|
4392
|
+
* Supports common cURL options:
|
|
4393
|
+
* - `-X, --request` - HTTP method
|
|
4394
|
+
* - `-H, --header` - Request headers
|
|
4395
|
+
* - `-d, --data, --data-raw, --data-binary` - Request body
|
|
4396
|
+
* - `-u, --user` - Basic authentication
|
|
4397
|
+
* - `-x, --proxy` - Proxy configuration
|
|
4398
|
+
* - `--socks5, --socks4` - SOCKS proxy
|
|
4399
|
+
* - `-L, --location` - Follow redirects
|
|
4400
|
+
* - `--max-redirs` - Maximum redirects
|
|
4401
|
+
* - `--max-time` - Request timeout
|
|
4402
|
+
* - `-k, --insecure` - Skip TLS verification
|
|
4403
|
+
* - `-A, --user-agent` - User agent header
|
|
4404
|
+
*
|
|
4405
|
+
* @param curlCommand - A cURL command string
|
|
4406
|
+
* @returns A request configuration object
|
|
4407
|
+
*
|
|
4408
|
+
* @example
|
|
4409
|
+
* ```typescript
|
|
4410
|
+
* // From browser DevTools "Copy as cURL"
|
|
4411
|
+
* const config = Rezo.fromCurl(`
|
|
4412
|
+
* curl 'https://api.example.com/data' \\
|
|
4413
|
+
* -H 'Authorization: Bearer token123' \\
|
|
4414
|
+
* -H 'Content-Type: application/json'
|
|
4415
|
+
* `);
|
|
4416
|
+
*
|
|
4417
|
+
* // Use with Rezo
|
|
4418
|
+
* const rezo = new Rezo();
|
|
4419
|
+
* const response = await rezo.request(config);
|
|
4420
|
+
* ```
|
|
4421
|
+
*/
|
|
4422
|
+
static fromCurl(curlCommand: string): RezoRequestOptions;
|
|
4358
4423
|
}
|
|
4359
4424
|
/**
|
|
4360
4425
|
* Extended Rezo instance with Axios-compatible static helpers.
|
|
@@ -4355,6 +4355,71 @@ export declare class Rezo {
|
|
|
4355
4355
|
* @see {@link cookieJar} - Access the underlying RezoCookieJar for more control
|
|
4356
4356
|
*/
|
|
4357
4357
|
clearCookies(): void;
|
|
4358
|
+
/**
|
|
4359
|
+
* Convert a Rezo request configuration to a cURL command string.
|
|
4360
|
+
*
|
|
4361
|
+
* Generates a valid cURL command that can be executed in a terminal to
|
|
4362
|
+
* reproduce the same HTTP request. Useful for:
|
|
4363
|
+
* - Debugging and sharing requests
|
|
4364
|
+
* - Documentation and examples
|
|
4365
|
+
* - Testing requests outside of Node.js
|
|
4366
|
+
* - Exporting requests to other tools
|
|
4367
|
+
*
|
|
4368
|
+
* @param config - Request configuration object
|
|
4369
|
+
* @returns A cURL command string
|
|
4370
|
+
*
|
|
4371
|
+
* @example
|
|
4372
|
+
* ```typescript
|
|
4373
|
+
* const curl = Rezo.toCurl({
|
|
4374
|
+
* url: 'https://api.example.com/users',
|
|
4375
|
+
* method: 'POST',
|
|
4376
|
+
* headers: { 'Content-Type': 'application/json' },
|
|
4377
|
+
* body: { name: 'John', email: 'john@example.com' }
|
|
4378
|
+
* });
|
|
4379
|
+
* // Output: curl -X POST -H 'content-type: application/json' --data-raw '{"name":"John","email":"john@example.com"}' -L --compressed 'https://api.example.com/users'
|
|
4380
|
+
* ```
|
|
4381
|
+
*/
|
|
4382
|
+
static toCurl(config: RezoRequestConfig | RezoRequestOptions): string;
|
|
4383
|
+
/**
|
|
4384
|
+
* Parse a cURL command string into a Rezo request configuration.
|
|
4385
|
+
*
|
|
4386
|
+
* Converts a cURL command into a configuration object that can be
|
|
4387
|
+
* passed directly to Rezo request methods. Useful for:
|
|
4388
|
+
* - Importing requests from browser DevTools
|
|
4389
|
+
* - Converting curl examples from API documentation
|
|
4390
|
+
* - Migrating scripts from curl to Rezo
|
|
4391
|
+
*
|
|
4392
|
+
* Supports common cURL options:
|
|
4393
|
+
* - `-X, --request` - HTTP method
|
|
4394
|
+
* - `-H, --header` - Request headers
|
|
4395
|
+
* - `-d, --data, --data-raw, --data-binary` - Request body
|
|
4396
|
+
* - `-u, --user` - Basic authentication
|
|
4397
|
+
* - `-x, --proxy` - Proxy configuration
|
|
4398
|
+
* - `--socks5, --socks4` - SOCKS proxy
|
|
4399
|
+
* - `-L, --location` - Follow redirects
|
|
4400
|
+
* - `--max-redirs` - Maximum redirects
|
|
4401
|
+
* - `--max-time` - Request timeout
|
|
4402
|
+
* - `-k, --insecure` - Skip TLS verification
|
|
4403
|
+
* - `-A, --user-agent` - User agent header
|
|
4404
|
+
*
|
|
4405
|
+
* @param curlCommand - A cURL command string
|
|
4406
|
+
* @returns A request configuration object
|
|
4407
|
+
*
|
|
4408
|
+
* @example
|
|
4409
|
+
* ```typescript
|
|
4410
|
+
* // From browser DevTools "Copy as cURL"
|
|
4411
|
+
* const config = Rezo.fromCurl(`
|
|
4412
|
+
* curl 'https://api.example.com/data' \\
|
|
4413
|
+
* -H 'Authorization: Bearer token123' \\
|
|
4414
|
+
* -H 'Content-Type: application/json'
|
|
4415
|
+
* `);
|
|
4416
|
+
*
|
|
4417
|
+
* // Use with Rezo
|
|
4418
|
+
* const rezo = new Rezo();
|
|
4419
|
+
* const response = await rezo.request(config);
|
|
4420
|
+
* ```
|
|
4421
|
+
*/
|
|
4422
|
+
static fromCurl(curlCommand: string): RezoRequestOptions;
|
|
4358
4423
|
}
|
|
4359
4424
|
/**
|
|
4360
4425
|
* Extended Rezo instance with Axios-compatible static helpers.
|
|
@@ -4355,6 +4355,71 @@ export declare class Rezo {
|
|
|
4355
4355
|
* @see {@link cookieJar} - Access the underlying RezoCookieJar for more control
|
|
4356
4356
|
*/
|
|
4357
4357
|
clearCookies(): void;
|
|
4358
|
+
/**
|
|
4359
|
+
* Convert a Rezo request configuration to a cURL command string.
|
|
4360
|
+
*
|
|
4361
|
+
* Generates a valid cURL command that can be executed in a terminal to
|
|
4362
|
+
* reproduce the same HTTP request. Useful for:
|
|
4363
|
+
* - Debugging and sharing requests
|
|
4364
|
+
* - Documentation and examples
|
|
4365
|
+
* - Testing requests outside of Node.js
|
|
4366
|
+
* - Exporting requests to other tools
|
|
4367
|
+
*
|
|
4368
|
+
* @param config - Request configuration object
|
|
4369
|
+
* @returns A cURL command string
|
|
4370
|
+
*
|
|
4371
|
+
* @example
|
|
4372
|
+
* ```typescript
|
|
4373
|
+
* const curl = Rezo.toCurl({
|
|
4374
|
+
* url: 'https://api.example.com/users',
|
|
4375
|
+
* method: 'POST',
|
|
4376
|
+
* headers: { 'Content-Type': 'application/json' },
|
|
4377
|
+
* body: { name: 'John', email: 'john@example.com' }
|
|
4378
|
+
* });
|
|
4379
|
+
* // Output: curl -X POST -H 'content-type: application/json' --data-raw '{"name":"John","email":"john@example.com"}' -L --compressed 'https://api.example.com/users'
|
|
4380
|
+
* ```
|
|
4381
|
+
*/
|
|
4382
|
+
static toCurl(config: RezoRequestConfig | RezoRequestOptions): string;
|
|
4383
|
+
/**
|
|
4384
|
+
* Parse a cURL command string into a Rezo request configuration.
|
|
4385
|
+
*
|
|
4386
|
+
* Converts a cURL command into a configuration object that can be
|
|
4387
|
+
* passed directly to Rezo request methods. Useful for:
|
|
4388
|
+
* - Importing requests from browser DevTools
|
|
4389
|
+
* - Converting curl examples from API documentation
|
|
4390
|
+
* - Migrating scripts from curl to Rezo
|
|
4391
|
+
*
|
|
4392
|
+
* Supports common cURL options:
|
|
4393
|
+
* - `-X, --request` - HTTP method
|
|
4394
|
+
* - `-H, --header` - Request headers
|
|
4395
|
+
* - `-d, --data, --data-raw, --data-binary` - Request body
|
|
4396
|
+
* - `-u, --user` - Basic authentication
|
|
4397
|
+
* - `-x, --proxy` - Proxy configuration
|
|
4398
|
+
* - `--socks5, --socks4` - SOCKS proxy
|
|
4399
|
+
* - `-L, --location` - Follow redirects
|
|
4400
|
+
* - `--max-redirs` - Maximum redirects
|
|
4401
|
+
* - `--max-time` - Request timeout
|
|
4402
|
+
* - `-k, --insecure` - Skip TLS verification
|
|
4403
|
+
* - `-A, --user-agent` - User agent header
|
|
4404
|
+
*
|
|
4405
|
+
* @param curlCommand - A cURL command string
|
|
4406
|
+
* @returns A request configuration object
|
|
4407
|
+
*
|
|
4408
|
+
* @example
|
|
4409
|
+
* ```typescript
|
|
4410
|
+
* // From browser DevTools "Copy as cURL"
|
|
4411
|
+
* const config = Rezo.fromCurl(`
|
|
4412
|
+
* curl 'https://api.example.com/data' \\
|
|
4413
|
+
* -H 'Authorization: Bearer token123' \\
|
|
4414
|
+
* -H 'Content-Type: application/json'
|
|
4415
|
+
* `);
|
|
4416
|
+
*
|
|
4417
|
+
* // Use with Rezo
|
|
4418
|
+
* const rezo = new Rezo();
|
|
4419
|
+
* const response = await rezo.request(config);
|
|
4420
|
+
* ```
|
|
4421
|
+
*/
|
|
4422
|
+
static fromCurl(curlCommand: string): RezoRequestOptions;
|
|
4358
4423
|
}
|
|
4359
4424
|
/**
|
|
4360
4425
|
* Extended Rezo instance with Axios-compatible static helpers.
|
package/dist/adapters/fetch.cjs
CHANGED
|
@@ -90,9 +90,24 @@ const debugLog = {
|
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
},
|
|
93
|
-
|
|
93
|
+
redirect: (config, fromUrl, toUrl, statusCode, method) => {
|
|
94
94
|
if (config.debug) {
|
|
95
|
-
console.log(`[Rezo Debug]
|
|
95
|
+
console.log(`[Rezo Debug] Redirect ${statusCode}: ${fromUrl}`);
|
|
96
|
+
console.log(`[Rezo Debug] → ${toUrl} (${method})`);
|
|
97
|
+
}
|
|
98
|
+
if (config.trackUrl) {
|
|
99
|
+
console.log(`[Rezo Track] ↳ ${statusCode} → ${toUrl}`);
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
complete: (config, url, redirectCount, duration) => {
|
|
103
|
+
if (config.debug) {
|
|
104
|
+
console.log(`[Rezo Debug] Complete: ${url}`);
|
|
105
|
+
if (redirectCount && redirectCount > 0) {
|
|
106
|
+
console.log(`[Rezo Debug] Redirects: ${redirectCount}`);
|
|
107
|
+
}
|
|
108
|
+
if (duration) {
|
|
109
|
+
console.log(`[Rezo Debug] Total Duration: ${duration.toFixed(2)}ms`);
|
|
110
|
+
}
|
|
96
111
|
console.log(`[Rezo Debug] ─────────────────────────────────────
|
|
97
112
|
`);
|
|
98
113
|
}
|
|
@@ -435,7 +450,7 @@ async function executeRequest(options, defaultOptions, jar) {
|
|
|
435
450
|
uploadResponse = new UploadResponse(url);
|
|
436
451
|
}
|
|
437
452
|
try {
|
|
438
|
-
const res = executeFetchRequest(fetchOptions, mainConfig, options, perform, streamResponse, downloadResponse, uploadResponse);
|
|
453
|
+
const res = executeFetchRequest(fetchOptions, mainConfig, options, perform, streamResponse, downloadResponse, uploadResponse, jar);
|
|
439
454
|
if (streamResponse) {
|
|
440
455
|
return streamResponse;
|
|
441
456
|
} else if (downloadResponse) {
|
|
@@ -462,7 +477,7 @@ async function executeRequest(options, defaultOptions, jar) {
|
|
|
462
477
|
throw error;
|
|
463
478
|
}
|
|
464
479
|
}
|
|
465
|
-
async function executeFetchRequest(fetchOptions, config, options, perform, streamResult, downloadResult, uploadResult) {
|
|
480
|
+
async function executeFetchRequest(fetchOptions, config, options, perform, streamResult, downloadResult, uploadResult, rootJar) {
|
|
466
481
|
let requestCount = 0;
|
|
467
482
|
const _stats = { statusOnNext: "abort" };
|
|
468
483
|
let retries = 0;
|
|
@@ -479,6 +494,11 @@ async function executeFetchRequest(fetchOptions, config, options, perform, strea
|
|
|
479
494
|
const visitedUrls = new Set;
|
|
480
495
|
let totalAttempts = 0;
|
|
481
496
|
config.setSignal();
|
|
497
|
+
if (!config.requestId) {
|
|
498
|
+
config.requestId = `req_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
|
|
499
|
+
}
|
|
500
|
+
const requestUrl = fetchOptions.fullUrl ? String(fetchOptions.fullUrl) : "";
|
|
501
|
+
debugLog.requestStart(config, requestUrl, fetchOptions.method || "GET");
|
|
482
502
|
const eventEmitter = streamResult || downloadResult || uploadResult;
|
|
483
503
|
if (eventEmitter) {
|
|
484
504
|
eventEmitter.emit("initiated");
|
|
@@ -530,6 +550,8 @@ async function executeFetchRequest(fetchOptions, config, options, perform, strea
|
|
|
530
550
|
continue;
|
|
531
551
|
}
|
|
532
552
|
if (statusOnNext === "success") {
|
|
553
|
+
const totalDuration = performance.now() - timing.startTime;
|
|
554
|
+
debugLog.complete(config, response.finalUrl || requestUrl, config.redirectCount, totalDuration);
|
|
533
555
|
return response;
|
|
534
556
|
}
|
|
535
557
|
if (statusOnNext === "error") {
|
|
@@ -579,12 +601,13 @@ async function executeFetchRequest(fetchOptions, config, options, perform, strea
|
|
|
579
601
|
status: response.status,
|
|
580
602
|
headers: response.headers,
|
|
581
603
|
sameDomain: isSameDomain(fetchOptions.fullUrl, location),
|
|
582
|
-
method: fetchOptions.method.toUpperCase()
|
|
604
|
+
method: fetchOptions.method.toUpperCase(),
|
|
605
|
+
body: config.originalBody
|
|
583
606
|
}) : undefined;
|
|
584
607
|
if (typeof onRedirect !== "undefined") {
|
|
585
608
|
if (typeof onRedirect === "boolean" && !onRedirect) {
|
|
586
609
|
throw builErrorFromResponse("Redirect denied by user", response, config, fetchOptions);
|
|
587
|
-
} else if (typeof onRedirect === "object" && !onRedirect.redirect) {
|
|
610
|
+
} else if (typeof onRedirect === "object" && !onRedirect.redirect && !onRedirect.withoutBody && !("body" in onRedirect)) {
|
|
588
611
|
throw builErrorFromResponse("Redirect denied by user", response, config, fetchOptions);
|
|
589
612
|
}
|
|
590
613
|
}
|
|
@@ -604,13 +627,78 @@ async function executeFetchRequest(fetchOptions, config, options, perform, strea
|
|
|
604
627
|
});
|
|
605
628
|
perform.reset();
|
|
606
629
|
config.redirectCount++;
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
630
|
+
const fromUrl = fetchOptions.fullUrl;
|
|
631
|
+
fetchOptions.fullUrl = location;
|
|
632
|
+
const normalizedRedirect = typeof onRedirect === "object" ? onRedirect.redirect || onRedirect.withoutBody || "body" in onRedirect : undefined;
|
|
633
|
+
if (typeof onRedirect === "object" && normalizedRedirect) {
|
|
634
|
+
let method;
|
|
635
|
+
const userMethod = onRedirect.method;
|
|
636
|
+
if (redirectCode === 301 || redirectCode === 302 || redirectCode === 303) {
|
|
637
|
+
method = userMethod || "GET";
|
|
638
|
+
} else {
|
|
639
|
+
method = userMethod || fetchOptions.method;
|
|
640
|
+
}
|
|
641
|
+
config.method = method;
|
|
642
|
+
options.method = method;
|
|
643
|
+
fetchOptions.method = method;
|
|
644
|
+
if (onRedirect.redirect && onRedirect.url) {
|
|
645
|
+
options.fullUrl = onRedirect.url;
|
|
646
|
+
fetchOptions.fullUrl = onRedirect.url;
|
|
647
|
+
}
|
|
648
|
+
if (onRedirect.withoutBody) {
|
|
649
|
+
delete options.body;
|
|
650
|
+
delete fetchOptions.body;
|
|
651
|
+
config.originalBody = undefined;
|
|
652
|
+
if (fetchOptions.headers instanceof RezoHeaders) {
|
|
653
|
+
fetchOptions.headers.delete("Content-Type");
|
|
654
|
+
fetchOptions.headers.delete("Content-Length");
|
|
655
|
+
}
|
|
656
|
+
} else if ("body" in onRedirect) {
|
|
657
|
+
options.body = onRedirect.body;
|
|
658
|
+
fetchOptions.body = onRedirect.body;
|
|
659
|
+
config.originalBody = onRedirect.body;
|
|
660
|
+
} else if (redirectCode === 307 || redirectCode === 308) {
|
|
661
|
+
const methodUpper = method.toUpperCase();
|
|
662
|
+
if ((methodUpper === "POST" || methodUpper === "PUT" || methodUpper === "PATCH") && config.originalBody !== undefined) {
|
|
663
|
+
options.body = config.originalBody;
|
|
664
|
+
fetchOptions.body = config.originalBody;
|
|
665
|
+
}
|
|
666
|
+
} else {
|
|
610
667
|
delete options.body;
|
|
668
|
+
delete fetchOptions.body;
|
|
669
|
+
if (fetchOptions.headers instanceof RezoHeaders) {
|
|
670
|
+
fetchOptions.headers.delete("Content-Type");
|
|
671
|
+
fetchOptions.headers.delete("Content-Length");
|
|
672
|
+
}
|
|
611
673
|
}
|
|
674
|
+
debugLog.redirect(config, fromUrl, fetchOptions.fullUrl, redirectCode, method);
|
|
675
|
+
if (onRedirect.redirect && onRedirect.setHeaders) {
|
|
676
|
+
if (fetchOptions.headers instanceof RezoHeaders) {
|
|
677
|
+
for (const [key, value] of Object.entries(onRedirect.setHeaders)) {
|
|
678
|
+
fetchOptions.headers.set(key, value);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
} else if (redirectCode === 301 || redirectCode === 302 || redirectCode === 303) {
|
|
683
|
+
debugLog.redirect(config, fromUrl, fetchOptions.fullUrl, redirectCode, "GET");
|
|
684
|
+
options.method = "GET";
|
|
685
|
+
fetchOptions.method = "GET";
|
|
686
|
+
config.method = "GET";
|
|
687
|
+
delete options.body;
|
|
688
|
+
delete fetchOptions.body;
|
|
689
|
+
if (fetchOptions.headers instanceof RezoHeaders) {
|
|
690
|
+
fetchOptions.headers.delete("Content-Type");
|
|
691
|
+
fetchOptions.headers.delete("Content-Length");
|
|
692
|
+
}
|
|
693
|
+
} else {
|
|
694
|
+
debugLog.redirect(config, fromUrl, fetchOptions.fullUrl, redirectCode, fetchOptions.method);
|
|
695
|
+
}
|
|
696
|
+
const jarToSync = rootJar || config.cookieJar;
|
|
697
|
+
if (response.cookies?.array?.length > 0 && jarToSync) {
|
|
698
|
+
try {
|
|
699
|
+
jarToSync.setCookiesSync(response.cookies.array, fromUrl);
|
|
700
|
+
} catch (e) {}
|
|
612
701
|
}
|
|
613
|
-
fetchOptions.fullUrl = location;
|
|
614
702
|
delete options.params;
|
|
615
703
|
requestCount++;
|
|
616
704
|
continue;
|
|
@@ -640,7 +728,6 @@ async function executeSingleFetchRequest(config, fetchOptions, requestCount, tim
|
|
|
640
728
|
} else if (config.transfer.requestSize === undefined) {
|
|
641
729
|
config.transfer.requestSize = 0;
|
|
642
730
|
}
|
|
643
|
-
debugLog.requestStart(config, url.href, fetchOptions.method?.toUpperCase() || "GET");
|
|
644
731
|
}
|
|
645
732
|
const reqHeaders = fetchOptions.headers instanceof RezoHeaders ? fetchOptions.headers.toObject() : fetchOptions.headers || {};
|
|
646
733
|
const headers = toFetchHeaders(reqHeaders);
|
|
@@ -903,7 +990,6 @@ async function executeSingleFetchRequest(config, fetchOptions, requestCount, tim
|
|
|
903
990
|
uploadResult.emit("done", uploadFinishEvent);
|
|
904
991
|
uploadResult._markFinished();
|
|
905
992
|
}
|
|
906
|
-
debugLog.complete(config, url.href);
|
|
907
993
|
return finalResponse;
|
|
908
994
|
} catch (error) {
|
|
909
995
|
_stats.statusOnNext = "error";
|
package/dist/adapters/fetch.js
CHANGED
|
@@ -90,9 +90,24 @@ const debugLog = {
|
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
},
|
|
93
|
-
|
|
93
|
+
redirect: (config, fromUrl, toUrl, statusCode, method) => {
|
|
94
94
|
if (config.debug) {
|
|
95
|
-
console.log(`[Rezo Debug]
|
|
95
|
+
console.log(`[Rezo Debug] Redirect ${statusCode}: ${fromUrl}`);
|
|
96
|
+
console.log(`[Rezo Debug] → ${toUrl} (${method})`);
|
|
97
|
+
}
|
|
98
|
+
if (config.trackUrl) {
|
|
99
|
+
console.log(`[Rezo Track] ↳ ${statusCode} → ${toUrl}`);
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
complete: (config, url, redirectCount, duration) => {
|
|
103
|
+
if (config.debug) {
|
|
104
|
+
console.log(`[Rezo Debug] Complete: ${url}`);
|
|
105
|
+
if (redirectCount && redirectCount > 0) {
|
|
106
|
+
console.log(`[Rezo Debug] Redirects: ${redirectCount}`);
|
|
107
|
+
}
|
|
108
|
+
if (duration) {
|
|
109
|
+
console.log(`[Rezo Debug] Total Duration: ${duration.toFixed(2)}ms`);
|
|
110
|
+
}
|
|
96
111
|
console.log(`[Rezo Debug] ─────────────────────────────────────
|
|
97
112
|
`);
|
|
98
113
|
}
|
|
@@ -435,7 +450,7 @@ export async function executeRequest(options, defaultOptions, jar) {
|
|
|
435
450
|
uploadResponse = new UploadResponse(url);
|
|
436
451
|
}
|
|
437
452
|
try {
|
|
438
|
-
const res = executeFetchRequest(fetchOptions, mainConfig, options, perform, streamResponse, downloadResponse, uploadResponse);
|
|
453
|
+
const res = executeFetchRequest(fetchOptions, mainConfig, options, perform, streamResponse, downloadResponse, uploadResponse, jar);
|
|
439
454
|
if (streamResponse) {
|
|
440
455
|
return streamResponse;
|
|
441
456
|
} else if (downloadResponse) {
|
|
@@ -462,7 +477,7 @@ export async function executeRequest(options, defaultOptions, jar) {
|
|
|
462
477
|
throw error;
|
|
463
478
|
}
|
|
464
479
|
}
|
|
465
|
-
async function executeFetchRequest(fetchOptions, config, options, perform, streamResult, downloadResult, uploadResult) {
|
|
480
|
+
async function executeFetchRequest(fetchOptions, config, options, perform, streamResult, downloadResult, uploadResult, rootJar) {
|
|
466
481
|
let requestCount = 0;
|
|
467
482
|
const _stats = { statusOnNext: "abort" };
|
|
468
483
|
let retries = 0;
|
|
@@ -479,6 +494,11 @@ async function executeFetchRequest(fetchOptions, config, options, perform, strea
|
|
|
479
494
|
const visitedUrls = new Set;
|
|
480
495
|
let totalAttempts = 0;
|
|
481
496
|
config.setSignal();
|
|
497
|
+
if (!config.requestId) {
|
|
498
|
+
config.requestId = `req_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
|
|
499
|
+
}
|
|
500
|
+
const requestUrl = fetchOptions.fullUrl ? String(fetchOptions.fullUrl) : "";
|
|
501
|
+
debugLog.requestStart(config, requestUrl, fetchOptions.method || "GET");
|
|
482
502
|
const eventEmitter = streamResult || downloadResult || uploadResult;
|
|
483
503
|
if (eventEmitter) {
|
|
484
504
|
eventEmitter.emit("initiated");
|
|
@@ -530,6 +550,8 @@ async function executeFetchRequest(fetchOptions, config, options, perform, strea
|
|
|
530
550
|
continue;
|
|
531
551
|
}
|
|
532
552
|
if (statusOnNext === "success") {
|
|
553
|
+
const totalDuration = performance.now() - timing.startTime;
|
|
554
|
+
debugLog.complete(config, response.finalUrl || requestUrl, config.redirectCount, totalDuration);
|
|
533
555
|
return response;
|
|
534
556
|
}
|
|
535
557
|
if (statusOnNext === "error") {
|
|
@@ -579,12 +601,13 @@ async function executeFetchRequest(fetchOptions, config, options, perform, strea
|
|
|
579
601
|
status: response.status,
|
|
580
602
|
headers: response.headers,
|
|
581
603
|
sameDomain: isSameDomain(fetchOptions.fullUrl, location),
|
|
582
|
-
method: fetchOptions.method.toUpperCase()
|
|
604
|
+
method: fetchOptions.method.toUpperCase(),
|
|
605
|
+
body: config.originalBody
|
|
583
606
|
}) : undefined;
|
|
584
607
|
if (typeof onRedirect !== "undefined") {
|
|
585
608
|
if (typeof onRedirect === "boolean" && !onRedirect) {
|
|
586
609
|
throw builErrorFromResponse("Redirect denied by user", response, config, fetchOptions);
|
|
587
|
-
} else if (typeof onRedirect === "object" && !onRedirect.redirect) {
|
|
610
|
+
} else if (typeof onRedirect === "object" && !onRedirect.redirect && !onRedirect.withoutBody && !("body" in onRedirect)) {
|
|
588
611
|
throw builErrorFromResponse("Redirect denied by user", response, config, fetchOptions);
|
|
589
612
|
}
|
|
590
613
|
}
|
|
@@ -604,13 +627,78 @@ async function executeFetchRequest(fetchOptions, config, options, perform, strea
|
|
|
604
627
|
});
|
|
605
628
|
perform.reset();
|
|
606
629
|
config.redirectCount++;
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
630
|
+
const fromUrl = fetchOptions.fullUrl;
|
|
631
|
+
fetchOptions.fullUrl = location;
|
|
632
|
+
const normalizedRedirect = typeof onRedirect === "object" ? onRedirect.redirect || onRedirect.withoutBody || "body" in onRedirect : undefined;
|
|
633
|
+
if (typeof onRedirect === "object" && normalizedRedirect) {
|
|
634
|
+
let method;
|
|
635
|
+
const userMethod = onRedirect.method;
|
|
636
|
+
if (redirectCode === 301 || redirectCode === 302 || redirectCode === 303) {
|
|
637
|
+
method = userMethod || "GET";
|
|
638
|
+
} else {
|
|
639
|
+
method = userMethod || fetchOptions.method;
|
|
640
|
+
}
|
|
641
|
+
config.method = method;
|
|
642
|
+
options.method = method;
|
|
643
|
+
fetchOptions.method = method;
|
|
644
|
+
if (onRedirect.redirect && onRedirect.url) {
|
|
645
|
+
options.fullUrl = onRedirect.url;
|
|
646
|
+
fetchOptions.fullUrl = onRedirect.url;
|
|
647
|
+
}
|
|
648
|
+
if (onRedirect.withoutBody) {
|
|
649
|
+
delete options.body;
|
|
650
|
+
delete fetchOptions.body;
|
|
651
|
+
config.originalBody = undefined;
|
|
652
|
+
if (fetchOptions.headers instanceof RezoHeaders) {
|
|
653
|
+
fetchOptions.headers.delete("Content-Type");
|
|
654
|
+
fetchOptions.headers.delete("Content-Length");
|
|
655
|
+
}
|
|
656
|
+
} else if ("body" in onRedirect) {
|
|
657
|
+
options.body = onRedirect.body;
|
|
658
|
+
fetchOptions.body = onRedirect.body;
|
|
659
|
+
config.originalBody = onRedirect.body;
|
|
660
|
+
} else if (redirectCode === 307 || redirectCode === 308) {
|
|
661
|
+
const methodUpper = method.toUpperCase();
|
|
662
|
+
if ((methodUpper === "POST" || methodUpper === "PUT" || methodUpper === "PATCH") && config.originalBody !== undefined) {
|
|
663
|
+
options.body = config.originalBody;
|
|
664
|
+
fetchOptions.body = config.originalBody;
|
|
665
|
+
}
|
|
666
|
+
} else {
|
|
610
667
|
delete options.body;
|
|
668
|
+
delete fetchOptions.body;
|
|
669
|
+
if (fetchOptions.headers instanceof RezoHeaders) {
|
|
670
|
+
fetchOptions.headers.delete("Content-Type");
|
|
671
|
+
fetchOptions.headers.delete("Content-Length");
|
|
672
|
+
}
|
|
611
673
|
}
|
|
674
|
+
debugLog.redirect(config, fromUrl, fetchOptions.fullUrl, redirectCode, method);
|
|
675
|
+
if (onRedirect.redirect && onRedirect.setHeaders) {
|
|
676
|
+
if (fetchOptions.headers instanceof RezoHeaders) {
|
|
677
|
+
for (const [key, value] of Object.entries(onRedirect.setHeaders)) {
|
|
678
|
+
fetchOptions.headers.set(key, value);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
} else if (redirectCode === 301 || redirectCode === 302 || redirectCode === 303) {
|
|
683
|
+
debugLog.redirect(config, fromUrl, fetchOptions.fullUrl, redirectCode, "GET");
|
|
684
|
+
options.method = "GET";
|
|
685
|
+
fetchOptions.method = "GET";
|
|
686
|
+
config.method = "GET";
|
|
687
|
+
delete options.body;
|
|
688
|
+
delete fetchOptions.body;
|
|
689
|
+
if (fetchOptions.headers instanceof RezoHeaders) {
|
|
690
|
+
fetchOptions.headers.delete("Content-Type");
|
|
691
|
+
fetchOptions.headers.delete("Content-Length");
|
|
692
|
+
}
|
|
693
|
+
} else {
|
|
694
|
+
debugLog.redirect(config, fromUrl, fetchOptions.fullUrl, redirectCode, fetchOptions.method);
|
|
695
|
+
}
|
|
696
|
+
const jarToSync = rootJar || config.cookieJar;
|
|
697
|
+
if (response.cookies?.array?.length > 0 && jarToSync) {
|
|
698
|
+
try {
|
|
699
|
+
jarToSync.setCookiesSync(response.cookies.array, fromUrl);
|
|
700
|
+
} catch (e) {}
|
|
612
701
|
}
|
|
613
|
-
fetchOptions.fullUrl = location;
|
|
614
702
|
delete options.params;
|
|
615
703
|
requestCount++;
|
|
616
704
|
continue;
|
|
@@ -640,7 +728,6 @@ async function executeSingleFetchRequest(config, fetchOptions, requestCount, tim
|
|
|
640
728
|
} else if (config.transfer.requestSize === undefined) {
|
|
641
729
|
config.transfer.requestSize = 0;
|
|
642
730
|
}
|
|
643
|
-
debugLog.requestStart(config, url.href, fetchOptions.method?.toUpperCase() || "GET");
|
|
644
731
|
}
|
|
645
732
|
const reqHeaders = fetchOptions.headers instanceof RezoHeaders ? fetchOptions.headers.toObject() : fetchOptions.headers || {};
|
|
646
733
|
const headers = toFetchHeaders(reqHeaders);
|
|
@@ -903,7 +990,6 @@ async function executeSingleFetchRequest(config, fetchOptions, requestCount, tim
|
|
|
903
990
|
uploadResult.emit("done", uploadFinishEvent);
|
|
904
991
|
uploadResult._markFinished();
|
|
905
992
|
}
|
|
906
|
-
debugLog.complete(config, url.href);
|
|
907
993
|
return finalResponse;
|
|
908
994
|
} catch (error) {
|
|
909
995
|
_stats.statusOnNext = "error";
|