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
package/dist/index.cjs
CHANGED
|
@@ -1,27 +1,30 @@
|
|
|
1
|
-
const
|
|
2
|
-
exports.Rezo =
|
|
3
|
-
exports.createRezoInstance =
|
|
4
|
-
exports.createDefaultInstance =
|
|
5
|
-
const
|
|
6
|
-
exports.RezoError =
|
|
7
|
-
exports.RezoErrorCode =
|
|
8
|
-
const
|
|
9
|
-
exports.RezoHeaders =
|
|
10
|
-
const
|
|
11
|
-
exports.RezoFormData =
|
|
12
|
-
const
|
|
13
|
-
exports.RezoCookieJar =
|
|
14
|
-
exports.Cookie =
|
|
15
|
-
const
|
|
16
|
-
exports.
|
|
17
|
-
exports.
|
|
18
|
-
const
|
|
19
|
-
exports.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
exports.
|
|
23
|
-
|
|
24
|
-
exports.
|
|
1
|
+
const _mod_ez6b8t = require('./core/rezo.cjs');
|
|
2
|
+
exports.Rezo = _mod_ez6b8t.Rezo;
|
|
3
|
+
exports.createRezoInstance = _mod_ez6b8t.createRezoInstance;
|
|
4
|
+
exports.createDefaultInstance = _mod_ez6b8t.createDefaultInstance;;
|
|
5
|
+
const _mod_3tc7ap = require('./errors/rezo-error.cjs');
|
|
6
|
+
exports.RezoError = _mod_3tc7ap.RezoError;
|
|
7
|
+
exports.RezoErrorCode = _mod_3tc7ap.RezoErrorCode;;
|
|
8
|
+
const _mod_43q7ms = require('./utils/headers.cjs');
|
|
9
|
+
exports.RezoHeaders = _mod_43q7ms.RezoHeaders;;
|
|
10
|
+
const _mod_g1j1lv = require('./utils/form-data.cjs');
|
|
11
|
+
exports.RezoFormData = _mod_g1j1lv.RezoFormData;;
|
|
12
|
+
const _mod_uvyhfd = require('./utils/cookies.cjs');
|
|
13
|
+
exports.RezoCookieJar = _mod_uvyhfd.RezoCookieJar;
|
|
14
|
+
exports.Cookie = _mod_uvyhfd.Cookie;;
|
|
15
|
+
const _mod_u7n5iq = require('./utils/curl.cjs');
|
|
16
|
+
exports.toCurl = _mod_u7n5iq.toCurl;
|
|
17
|
+
exports.fromCurl = _mod_u7n5iq.fromCurl;;
|
|
18
|
+
const _mod_dk9wem = require('./core/hooks.cjs');
|
|
19
|
+
exports.createDefaultHooks = _mod_dk9wem.createDefaultHooks;
|
|
20
|
+
exports.mergeHooks = _mod_dk9wem.mergeHooks;;
|
|
21
|
+
const _mod_pe26um = require('./proxy/manager.cjs');
|
|
22
|
+
exports.ProxyManager = _mod_pe26um.ProxyManager;;
|
|
23
|
+
const _mod_zl76ch = require('./queue/index.cjs');
|
|
24
|
+
exports.RezoQueue = _mod_zl76ch.RezoQueue;
|
|
25
|
+
exports.HttpQueue = _mod_zl76ch.HttpQueue;
|
|
26
|
+
exports.Priority = _mod_zl76ch.Priority;
|
|
27
|
+
exports.HttpMethodPriority = _mod_zl76ch.HttpMethodPriority;;
|
|
25
28
|
const { RezoError } = require('./errors/rezo-error.cjs');
|
|
26
29
|
const isRezoError = exports.isRezoError = RezoError.isRezoError;
|
|
27
30
|
const Cancel = exports.Cancel = RezoError;
|
package/dist/index.d.ts
CHANGED
|
@@ -4217,6 +4217,14 @@ export interface httpAdapterPutOverloads {
|
|
|
4217
4217
|
responseType: "upload";
|
|
4218
4218
|
}): Promise<RezoUploadResponse>;
|
|
4219
4219
|
}
|
|
4220
|
+
/**
|
|
4221
|
+
* Convert a Rezo request configuration to a cURL command string.
|
|
4222
|
+
*/
|
|
4223
|
+
export declare function toCurl(config: RezoRequestConfig | RezoRequestOptions): string;
|
|
4224
|
+
/**
|
|
4225
|
+
* Parse a cURL command string into a Rezo request configuration.
|
|
4226
|
+
*/
|
|
4227
|
+
export declare function fromCurl(curlCommand: string): RezoRequestOptions;
|
|
4220
4228
|
/**
|
|
4221
4229
|
* Adapter function type - all adapters must implement this signature
|
|
4222
4230
|
*/
|
|
@@ -4500,6 +4508,71 @@ export declare class Rezo {
|
|
|
4500
4508
|
* @see {@link cookieJar} - Access the underlying RezoCookieJar for more control
|
|
4501
4509
|
*/
|
|
4502
4510
|
clearCookies(): void;
|
|
4511
|
+
/**
|
|
4512
|
+
* Convert a Rezo request configuration to a cURL command string.
|
|
4513
|
+
*
|
|
4514
|
+
* Generates a valid cURL command that can be executed in a terminal to
|
|
4515
|
+
* reproduce the same HTTP request. Useful for:
|
|
4516
|
+
* - Debugging and sharing requests
|
|
4517
|
+
* - Documentation and examples
|
|
4518
|
+
* - Testing requests outside of Node.js
|
|
4519
|
+
* - Exporting requests to other tools
|
|
4520
|
+
*
|
|
4521
|
+
* @param config - Request configuration object
|
|
4522
|
+
* @returns A cURL command string
|
|
4523
|
+
*
|
|
4524
|
+
* @example
|
|
4525
|
+
* ```typescript
|
|
4526
|
+
* const curl = Rezo.toCurl({
|
|
4527
|
+
* url: 'https://api.example.com/users',
|
|
4528
|
+
* method: 'POST',
|
|
4529
|
+
* headers: { 'Content-Type': 'application/json' },
|
|
4530
|
+
* body: { name: 'John', email: 'john@example.com' }
|
|
4531
|
+
* });
|
|
4532
|
+
* // Output: curl -X POST -H 'content-type: application/json' --data-raw '{"name":"John","email":"john@example.com"}' -L --compressed 'https://api.example.com/users'
|
|
4533
|
+
* ```
|
|
4534
|
+
*/
|
|
4535
|
+
static toCurl(config: RezoRequestConfig | RezoRequestOptions): string;
|
|
4536
|
+
/**
|
|
4537
|
+
* Parse a cURL command string into a Rezo request configuration.
|
|
4538
|
+
*
|
|
4539
|
+
* Converts a cURL command into a configuration object that can be
|
|
4540
|
+
* passed directly to Rezo request methods. Useful for:
|
|
4541
|
+
* - Importing requests from browser DevTools
|
|
4542
|
+
* - Converting curl examples from API documentation
|
|
4543
|
+
* - Migrating scripts from curl to Rezo
|
|
4544
|
+
*
|
|
4545
|
+
* Supports common cURL options:
|
|
4546
|
+
* - `-X, --request` - HTTP method
|
|
4547
|
+
* - `-H, --header` - Request headers
|
|
4548
|
+
* - `-d, --data, --data-raw, --data-binary` - Request body
|
|
4549
|
+
* - `-u, --user` - Basic authentication
|
|
4550
|
+
* - `-x, --proxy` - Proxy configuration
|
|
4551
|
+
* - `--socks5, --socks4` - SOCKS proxy
|
|
4552
|
+
* - `-L, --location` - Follow redirects
|
|
4553
|
+
* - `--max-redirs` - Maximum redirects
|
|
4554
|
+
* - `--max-time` - Request timeout
|
|
4555
|
+
* - `-k, --insecure` - Skip TLS verification
|
|
4556
|
+
* - `-A, --user-agent` - User agent header
|
|
4557
|
+
*
|
|
4558
|
+
* @param curlCommand - A cURL command string
|
|
4559
|
+
* @returns A request configuration object
|
|
4560
|
+
*
|
|
4561
|
+
* @example
|
|
4562
|
+
* ```typescript
|
|
4563
|
+
* // From browser DevTools "Copy as cURL"
|
|
4564
|
+
* const config = Rezo.fromCurl(`
|
|
4565
|
+
* curl 'https://api.example.com/data' \\
|
|
4566
|
+
* -H 'Authorization: Bearer token123' \\
|
|
4567
|
+
* -H 'Content-Type: application/json'
|
|
4568
|
+
* `);
|
|
4569
|
+
*
|
|
4570
|
+
* // Use with Rezo
|
|
4571
|
+
* const rezo = new Rezo();
|
|
4572
|
+
* const response = await rezo.request(config);
|
|
4573
|
+
* ```
|
|
4574
|
+
*/
|
|
4575
|
+
static fromCurl(curlCommand: string): RezoRequestOptions;
|
|
4503
4576
|
}
|
|
4504
4577
|
/**
|
|
4505
4578
|
* Extended Rezo instance with Axios-compatible static helpers.
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ export { RezoError, RezoErrorCode } from './errors/rezo-error.js';
|
|
|
7
7
|
export { RezoHeaders } from './utils/headers.js';
|
|
8
8
|
export { RezoFormData } from './utils/form-data.js';
|
|
9
9
|
export { RezoCookieJar, Cookie } from './utils/cookies.js';
|
|
10
|
+
export { toCurl, fromCurl } from './utils/curl.js';
|
|
10
11
|
export { createDefaultHooks, mergeHooks } from './core/hooks.js';
|
|
11
12
|
export { ProxyManager } from './proxy/manager.js';
|
|
12
13
|
export { RezoQueue, HttpQueue, Priority, HttpMethodPriority } from './queue/index.js';
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
const net = require("node:net");
|
|
2
|
+
const http = require("node:http");
|
|
3
|
+
const https = require("node:https");
|
|
4
|
+
const INTERNAL = Symbol("AgentBaseInternalState");
|
|
5
|
+
|
|
6
|
+
class Agent extends http.Agent {
|
|
7
|
+
[INTERNAL] = {};
|
|
8
|
+
constructor(opts) {
|
|
9
|
+
super(opts);
|
|
10
|
+
}
|
|
11
|
+
isSecureEndpoint(options) {
|
|
12
|
+
if (options) {
|
|
13
|
+
if (typeof options.secureEndpoint === "boolean") {
|
|
14
|
+
return options.secureEndpoint;
|
|
15
|
+
}
|
|
16
|
+
if (typeof options.protocol === "string") {
|
|
17
|
+
return options.protocol === "https:";
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const { stack } = new Error;
|
|
21
|
+
if (typeof stack !== "string")
|
|
22
|
+
return false;
|
|
23
|
+
return stack.split(`
|
|
24
|
+
`).some((l) => l.indexOf("(https.js:") !== -1 || l.indexOf("node:https:") !== -1);
|
|
25
|
+
}
|
|
26
|
+
incrementSockets(name) {
|
|
27
|
+
if (this.maxSockets === 1 / 0 && this.maxTotalSockets === 1 / 0) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
if (!this.sockets[name]) {
|
|
31
|
+
this.sockets[name] = [];
|
|
32
|
+
}
|
|
33
|
+
const fakeSocket = new net.Socket({ writable: false });
|
|
34
|
+
this.sockets[name].push(fakeSocket);
|
|
35
|
+
this.totalSocketCount++;
|
|
36
|
+
return fakeSocket;
|
|
37
|
+
}
|
|
38
|
+
decrementSockets(name, socket) {
|
|
39
|
+
if (!this.sockets[name] || socket === null) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const sockets = this.sockets[name];
|
|
43
|
+
const index = sockets.indexOf(socket);
|
|
44
|
+
if (index !== -1) {
|
|
45
|
+
sockets.splice(index, 1);
|
|
46
|
+
this.totalSocketCount--;
|
|
47
|
+
if (sockets.length === 0) {
|
|
48
|
+
delete this.sockets[name];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
getName(options) {
|
|
53
|
+
const secureEndpoint = this.isSecureEndpoint(options);
|
|
54
|
+
if (secureEndpoint) {
|
|
55
|
+
return https.Agent.prototype.getName.call(this, options);
|
|
56
|
+
}
|
|
57
|
+
return http.Agent.prototype.getName.call(this, options);
|
|
58
|
+
}
|
|
59
|
+
createSocket(req, options, cb) {
|
|
60
|
+
const connectOpts = {
|
|
61
|
+
...options,
|
|
62
|
+
secureEndpoint: this.isSecureEndpoint(options)
|
|
63
|
+
};
|
|
64
|
+
const name = this.getName(connectOpts);
|
|
65
|
+
const fakeSocket = this.incrementSockets(name);
|
|
66
|
+
Promise.resolve().then(() => this.connect(req, connectOpts)).then((socket) => {
|
|
67
|
+
this.decrementSockets(name, fakeSocket);
|
|
68
|
+
if (socket instanceof http.Agent) {
|
|
69
|
+
try {
|
|
70
|
+
return socket.addRequest(req, connectOpts);
|
|
71
|
+
} catch (err) {
|
|
72
|
+
return cb(err);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
this[INTERNAL].currentSocket = socket;
|
|
76
|
+
http.Agent.prototype.createSocket.call(this, req, options, cb);
|
|
77
|
+
}, (err) => {
|
|
78
|
+
this.decrementSockets(name, fakeSocket);
|
|
79
|
+
cb(err);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
createConnection() {
|
|
83
|
+
const socket = this[INTERNAL].currentSocket;
|
|
84
|
+
this[INTERNAL].currentSocket = undefined;
|
|
85
|
+
if (!socket) {
|
|
86
|
+
throw new Error("No socket was returned in the `connect()` function");
|
|
87
|
+
}
|
|
88
|
+
return socket;
|
|
89
|
+
}
|
|
90
|
+
async connect(_req, _opts) {
|
|
91
|
+
throw new Error("`connect()` must be implemented by a subclass of `Agent`");
|
|
92
|
+
}
|
|
93
|
+
get defaultPort() {
|
|
94
|
+
return this[INTERNAL].defaultPort ?? (this.protocol === "https:" ? 443 : 80);
|
|
95
|
+
}
|
|
96
|
+
set defaultPort(v) {
|
|
97
|
+
if (this[INTERNAL]) {
|
|
98
|
+
this[INTERNAL].defaultPort = v;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
get protocol() {
|
|
102
|
+
return this[INTERNAL].protocol ?? (this.isSecureEndpoint() ? "https:" : "http:");
|
|
103
|
+
}
|
|
104
|
+
set protocol(v) {
|
|
105
|
+
if (this[INTERNAL]) {
|
|
106
|
+
this[INTERNAL].protocol = v;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
exports.Agent = Agent;
|
|
112
|
+
exports.default = Agent;
|
|
113
|
+
module.exports = Object.assign(Agent, exports);
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import * as net from "node:net";
|
|
2
|
+
import * as http from "node:http";
|
|
3
|
+
import * as https from "node:https";
|
|
4
|
+
const INTERNAL = Symbol("AgentBaseInternalState");
|
|
5
|
+
|
|
6
|
+
export class Agent extends http.Agent {
|
|
7
|
+
[INTERNAL] = {};
|
|
8
|
+
constructor(opts) {
|
|
9
|
+
super(opts);
|
|
10
|
+
}
|
|
11
|
+
isSecureEndpoint(options) {
|
|
12
|
+
if (options) {
|
|
13
|
+
if (typeof options.secureEndpoint === "boolean") {
|
|
14
|
+
return options.secureEndpoint;
|
|
15
|
+
}
|
|
16
|
+
if (typeof options.protocol === "string") {
|
|
17
|
+
return options.protocol === "https:";
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const { stack } = new Error;
|
|
21
|
+
if (typeof stack !== "string")
|
|
22
|
+
return false;
|
|
23
|
+
return stack.split(`
|
|
24
|
+
`).some((l) => l.indexOf("(https.js:") !== -1 || l.indexOf("node:https:") !== -1);
|
|
25
|
+
}
|
|
26
|
+
incrementSockets(name) {
|
|
27
|
+
if (this.maxSockets === 1 / 0 && this.maxTotalSockets === 1 / 0) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
if (!this.sockets[name]) {
|
|
31
|
+
this.sockets[name] = [];
|
|
32
|
+
}
|
|
33
|
+
const fakeSocket = new net.Socket({ writable: false });
|
|
34
|
+
this.sockets[name].push(fakeSocket);
|
|
35
|
+
this.totalSocketCount++;
|
|
36
|
+
return fakeSocket;
|
|
37
|
+
}
|
|
38
|
+
decrementSockets(name, socket) {
|
|
39
|
+
if (!this.sockets[name] || socket === null) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const sockets = this.sockets[name];
|
|
43
|
+
const index = sockets.indexOf(socket);
|
|
44
|
+
if (index !== -1) {
|
|
45
|
+
sockets.splice(index, 1);
|
|
46
|
+
this.totalSocketCount--;
|
|
47
|
+
if (sockets.length === 0) {
|
|
48
|
+
delete this.sockets[name];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
getName(options) {
|
|
53
|
+
const secureEndpoint = this.isSecureEndpoint(options);
|
|
54
|
+
if (secureEndpoint) {
|
|
55
|
+
return https.Agent.prototype.getName.call(this, options);
|
|
56
|
+
}
|
|
57
|
+
return http.Agent.prototype.getName.call(this, options);
|
|
58
|
+
}
|
|
59
|
+
createSocket(req, options, cb) {
|
|
60
|
+
const connectOpts = {
|
|
61
|
+
...options,
|
|
62
|
+
secureEndpoint: this.isSecureEndpoint(options)
|
|
63
|
+
};
|
|
64
|
+
const name = this.getName(connectOpts);
|
|
65
|
+
const fakeSocket = this.incrementSockets(name);
|
|
66
|
+
Promise.resolve().then(() => this.connect(req, connectOpts)).then((socket) => {
|
|
67
|
+
this.decrementSockets(name, fakeSocket);
|
|
68
|
+
if (socket instanceof http.Agent) {
|
|
69
|
+
try {
|
|
70
|
+
return socket.addRequest(req, connectOpts);
|
|
71
|
+
} catch (err) {
|
|
72
|
+
return cb(err);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
this[INTERNAL].currentSocket = socket;
|
|
76
|
+
http.Agent.prototype.createSocket.call(this, req, options, cb);
|
|
77
|
+
}, (err) => {
|
|
78
|
+
this.decrementSockets(name, fakeSocket);
|
|
79
|
+
cb(err);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
createConnection() {
|
|
83
|
+
const socket = this[INTERNAL].currentSocket;
|
|
84
|
+
this[INTERNAL].currentSocket = undefined;
|
|
85
|
+
if (!socket) {
|
|
86
|
+
throw new Error("No socket was returned in the `connect()` function");
|
|
87
|
+
}
|
|
88
|
+
return socket;
|
|
89
|
+
}
|
|
90
|
+
async connect(_req, _opts) {
|
|
91
|
+
throw new Error("`connect()` must be implemented by a subclass of `Agent`");
|
|
92
|
+
}
|
|
93
|
+
get defaultPort() {
|
|
94
|
+
return this[INTERNAL].defaultPort ?? (this.protocol === "https:" ? 443 : 80);
|
|
95
|
+
}
|
|
96
|
+
set defaultPort(v) {
|
|
97
|
+
if (this[INTERNAL]) {
|
|
98
|
+
this[INTERNAL].defaultPort = v;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
get protocol() {
|
|
102
|
+
return this[INTERNAL].protocol ?? (this.isSecureEndpoint() ? "https:" : "http:");
|
|
103
|
+
}
|
|
104
|
+
set protocol(v) {
|
|
105
|
+
if (this[INTERNAL]) {
|
|
106
|
+
this[INTERNAL].protocol = v;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
export default Agent;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
const net = require("node:net");
|
|
2
|
+
const tls = require("node:tls");
|
|
3
|
+
const http = require("node:http");
|
|
4
|
+
const { once } = require("node:events");
|
|
5
|
+
const { Agent } = require('./base.cjs');
|
|
6
|
+
function omit(obj, ...keys) {
|
|
7
|
+
const ret = {};
|
|
8
|
+
for (const key in obj) {
|
|
9
|
+
if (!keys.includes(key)) {
|
|
10
|
+
ret[key] = obj[key];
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return ret;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
class HttpProxyAgent extends Agent {
|
|
17
|
+
static protocols = ["http", "https"];
|
|
18
|
+
proxy;
|
|
19
|
+
proxyHeaders;
|
|
20
|
+
connectOpts;
|
|
21
|
+
constructor(proxy, opts) {
|
|
22
|
+
super(opts);
|
|
23
|
+
this.proxy = typeof proxy === "string" ? new URL(proxy) : proxy;
|
|
24
|
+
this.proxyHeaders = opts?.headers ?? {};
|
|
25
|
+
const host = (this.proxy.hostname || this.proxy.host).replace(/^\[|\]$/g, "");
|
|
26
|
+
const port = this.proxy.port ? parseInt(this.proxy.port, 10) : this.proxy.protocol === "https:" ? 443 : 80;
|
|
27
|
+
this.connectOpts = {
|
|
28
|
+
...opts ? omit(opts, "headers") : {},
|
|
29
|
+
host,
|
|
30
|
+
port
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
addRequest(req, opts) {
|
|
34
|
+
req._header = null;
|
|
35
|
+
this.setRequestProps(req, opts);
|
|
36
|
+
http.Agent.prototype.addRequest.call(this, req, opts);
|
|
37
|
+
}
|
|
38
|
+
setRequestProps(req, opts) {
|
|
39
|
+
const { proxy } = this;
|
|
40
|
+
const protocol = opts.secureEndpoint ? "https:" : "http:";
|
|
41
|
+
const hostname = req.getHeader("host") || "localhost";
|
|
42
|
+
const base = `${protocol}//${hostname}`;
|
|
43
|
+
const url = new URL(req.path, base);
|
|
44
|
+
if (opts.port !== 80) {
|
|
45
|
+
url.port = String(opts.port);
|
|
46
|
+
}
|
|
47
|
+
req.path = String(url);
|
|
48
|
+
const headers = typeof this.proxyHeaders === "function" ? this.proxyHeaders() : { ...this.proxyHeaders };
|
|
49
|
+
if (proxy.username || proxy.password) {
|
|
50
|
+
const auth = `${decodeURIComponent(proxy.username)}:${decodeURIComponent(proxy.password)}`;
|
|
51
|
+
headers["Proxy-Authorization"] = `Basic ${Buffer.from(auth).toString("base64")}`;
|
|
52
|
+
}
|
|
53
|
+
if (!headers["Proxy-Connection"]) {
|
|
54
|
+
headers["Proxy-Connection"] = this.keepAlive ? "Keep-Alive" : "close";
|
|
55
|
+
}
|
|
56
|
+
for (const name of Object.keys(headers)) {
|
|
57
|
+
const value = headers[name];
|
|
58
|
+
if (value) {
|
|
59
|
+
req.setHeader(name, value);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async connect(req, opts) {
|
|
64
|
+
req._header = null;
|
|
65
|
+
if (!req.path.includes("://")) {
|
|
66
|
+
this.setRequestProps(req, opts);
|
|
67
|
+
}
|
|
68
|
+
req._implicitHeader();
|
|
69
|
+
if (req.outputData && req.outputData.length > 0) {
|
|
70
|
+
const first = req.outputData[0].data;
|
|
71
|
+
const endOfHeaders = first.indexOf(`\r
|
|
72
|
+
\r
|
|
73
|
+
`) + 4;
|
|
74
|
+
req.outputData[0].data = req._header + first.substring(endOfHeaders);
|
|
75
|
+
}
|
|
76
|
+
let socket;
|
|
77
|
+
if (this.proxy.protocol === "https:") {
|
|
78
|
+
socket = tls.connect(this.connectOpts);
|
|
79
|
+
} else {
|
|
80
|
+
socket = net.connect(this.connectOpts);
|
|
81
|
+
}
|
|
82
|
+
await once(socket, "connect");
|
|
83
|
+
return socket;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
exports.HttpProxyAgent = HttpProxyAgent;
|
|
88
|
+
exports.default = HttpProxyAgent;
|
|
89
|
+
module.exports = Object.assign(HttpProxyAgent, exports);
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import * as net from "node:net";
|
|
2
|
+
import * as tls from "node:tls";
|
|
3
|
+
import * as http from "node:http";
|
|
4
|
+
import { once } from "node:events";
|
|
5
|
+
import { Agent } from './base.js';
|
|
6
|
+
function omit(obj, ...keys) {
|
|
7
|
+
const ret = {};
|
|
8
|
+
for (const key in obj) {
|
|
9
|
+
if (!keys.includes(key)) {
|
|
10
|
+
ret[key] = obj[key];
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return ret;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export class HttpProxyAgent extends Agent {
|
|
17
|
+
static protocols = ["http", "https"];
|
|
18
|
+
proxy;
|
|
19
|
+
proxyHeaders;
|
|
20
|
+
connectOpts;
|
|
21
|
+
constructor(proxy, opts) {
|
|
22
|
+
super(opts);
|
|
23
|
+
this.proxy = typeof proxy === "string" ? new URL(proxy) : proxy;
|
|
24
|
+
this.proxyHeaders = opts?.headers ?? {};
|
|
25
|
+
const host = (this.proxy.hostname || this.proxy.host).replace(/^\[|\]$/g, "");
|
|
26
|
+
const port = this.proxy.port ? parseInt(this.proxy.port, 10) : this.proxy.protocol === "https:" ? 443 : 80;
|
|
27
|
+
this.connectOpts = {
|
|
28
|
+
...opts ? omit(opts, "headers") : {},
|
|
29
|
+
host,
|
|
30
|
+
port
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
addRequest(req, opts) {
|
|
34
|
+
req._header = null;
|
|
35
|
+
this.setRequestProps(req, opts);
|
|
36
|
+
http.Agent.prototype.addRequest.call(this, req, opts);
|
|
37
|
+
}
|
|
38
|
+
setRequestProps(req, opts) {
|
|
39
|
+
const { proxy } = this;
|
|
40
|
+
const protocol = opts.secureEndpoint ? "https:" : "http:";
|
|
41
|
+
const hostname = req.getHeader("host") || "localhost";
|
|
42
|
+
const base = `${protocol}//${hostname}`;
|
|
43
|
+
const url = new URL(req.path, base);
|
|
44
|
+
if (opts.port !== 80) {
|
|
45
|
+
url.port = String(opts.port);
|
|
46
|
+
}
|
|
47
|
+
req.path = String(url);
|
|
48
|
+
const headers = typeof this.proxyHeaders === "function" ? this.proxyHeaders() : { ...this.proxyHeaders };
|
|
49
|
+
if (proxy.username || proxy.password) {
|
|
50
|
+
const auth = `${decodeURIComponent(proxy.username)}:${decodeURIComponent(proxy.password)}`;
|
|
51
|
+
headers["Proxy-Authorization"] = `Basic ${Buffer.from(auth).toString("base64")}`;
|
|
52
|
+
}
|
|
53
|
+
if (!headers["Proxy-Connection"]) {
|
|
54
|
+
headers["Proxy-Connection"] = this.keepAlive ? "Keep-Alive" : "close";
|
|
55
|
+
}
|
|
56
|
+
for (const name of Object.keys(headers)) {
|
|
57
|
+
const value = headers[name];
|
|
58
|
+
if (value) {
|
|
59
|
+
req.setHeader(name, value);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async connect(req, opts) {
|
|
64
|
+
req._header = null;
|
|
65
|
+
if (!req.path.includes("://")) {
|
|
66
|
+
this.setRequestProps(req, opts);
|
|
67
|
+
}
|
|
68
|
+
req._implicitHeader();
|
|
69
|
+
if (req.outputData && req.outputData.length > 0) {
|
|
70
|
+
const first = req.outputData[0].data;
|
|
71
|
+
const endOfHeaders = first.indexOf(`\r
|
|
72
|
+
\r
|
|
73
|
+
`) + 4;
|
|
74
|
+
req.outputData[0].data = req._header + first.substring(endOfHeaders);
|
|
75
|
+
}
|
|
76
|
+
let socket;
|
|
77
|
+
if (this.proxy.protocol === "https:") {
|
|
78
|
+
socket = tls.connect(this.connectOpts);
|
|
79
|
+
} else {
|
|
80
|
+
socket = net.connect(this.connectOpts);
|
|
81
|
+
}
|
|
82
|
+
await once(socket, "connect");
|
|
83
|
+
return socket;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
export default HttpProxyAgent;
|