rezo 1.0.42 → 1.0.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/dist/adapters/curl.cjs +131 -29
  2. package/dist/adapters/curl.js +131 -29
  3. package/dist/adapters/entries/curl.d.ts +65 -0
  4. package/dist/adapters/entries/fetch.d.ts +65 -0
  5. package/dist/adapters/entries/http.d.ts +65 -0
  6. package/dist/adapters/entries/http2.d.ts +65 -0
  7. package/dist/adapters/entries/react-native.d.ts +65 -0
  8. package/dist/adapters/entries/xhr.d.ts +65 -0
  9. package/dist/adapters/http2.cjs +209 -22
  10. package/dist/adapters/http2.js +209 -22
  11. package/dist/adapters/index.cjs +6 -6
  12. package/dist/cache/index.cjs +9 -13
  13. package/dist/cache/index.js +0 -2
  14. package/dist/core/rezo.cjs +7 -0
  15. package/dist/core/rezo.js +7 -0
  16. package/dist/crawler/addon/decodo/index.cjs +1 -0
  17. package/dist/crawler/addon/decodo/index.js +1 -0
  18. package/dist/crawler/crawler-options.cjs +1 -0
  19. package/dist/crawler/crawler-options.js +1 -0
  20. package/dist/crawler/crawler.cjs +1070 -0
  21. package/dist/crawler/crawler.js +1068 -0
  22. package/dist/crawler/index.cjs +40 -0
  23. package/dist/{plugin → crawler}/index.js +4 -2
  24. package/dist/crawler/plugin/file-cacher.cjs +19 -0
  25. package/dist/crawler/plugin/file-cacher.js +19 -0
  26. package/dist/crawler/plugin/index.cjs +1 -0
  27. package/dist/crawler/plugin/index.js +1 -0
  28. package/dist/crawler/plugin/navigation-history.cjs +43 -0
  29. package/dist/crawler/plugin/navigation-history.js +43 -0
  30. package/dist/crawler/plugin/robots-txt.cjs +2 -0
  31. package/dist/crawler/plugin/robots-txt.js +2 -0
  32. package/dist/crawler/plugin/url-store.cjs +18 -0
  33. package/dist/crawler/plugin/url-store.js +18 -0
  34. package/dist/crawler.d.ts +511 -183
  35. package/dist/entries/crawler.cjs +5 -5
  36. package/dist/entries/crawler.js +2 -2
  37. package/dist/index.cjs +27 -24
  38. package/dist/index.d.ts +73 -0
  39. package/dist/index.js +1 -0
  40. package/dist/internal/agents/base.cjs +113 -0
  41. package/dist/internal/agents/base.js +110 -0
  42. package/dist/internal/agents/http-proxy.cjs +89 -0
  43. package/dist/internal/agents/http-proxy.js +86 -0
  44. package/dist/internal/agents/https-proxy.cjs +176 -0
  45. package/dist/internal/agents/https-proxy.js +173 -0
  46. package/dist/internal/agents/index.cjs +10 -0
  47. package/dist/internal/agents/index.js +5 -0
  48. package/dist/internal/agents/socks-client.cjs +571 -0
  49. package/dist/internal/agents/socks-client.js +567 -0
  50. package/dist/internal/agents/socks-proxy.cjs +75 -0
  51. package/dist/internal/agents/socks-proxy.js +72 -0
  52. package/dist/platform/browser.d.ts +65 -0
  53. package/dist/platform/bun.d.ts +65 -0
  54. package/dist/platform/deno.d.ts +65 -0
  55. package/dist/platform/node.d.ts +65 -0
  56. package/dist/platform/react-native.d.ts +65 -0
  57. package/dist/platform/worker.d.ts +65 -0
  58. package/dist/proxy/index.cjs +18 -16
  59. package/dist/proxy/index.js +17 -12
  60. package/dist/queue/index.cjs +8 -8
  61. package/dist/responses/buildError.cjs +11 -2
  62. package/dist/responses/buildError.js +11 -2
  63. package/dist/responses/universal/index.cjs +11 -11
  64. package/dist/utils/curl.cjs +317 -0
  65. package/dist/utils/curl.js +314 -0
  66. package/package.json +2 -6
  67. package/dist/cache/file-cacher.cjs +0 -264
  68. package/dist/cache/file-cacher.js +0 -261
  69. package/dist/cache/url-store.cjs +0 -288
  70. package/dist/cache/url-store.js +0 -285
  71. package/dist/plugin/addon/decodo/index.cjs +0 -1
  72. package/dist/plugin/addon/decodo/index.js +0 -1
  73. package/dist/plugin/crawler-options.cjs +0 -1
  74. package/dist/plugin/crawler-options.js +0 -1
  75. package/dist/plugin/crawler.cjs +0 -519
  76. package/dist/plugin/crawler.js +0 -517
  77. package/dist/plugin/index.cjs +0 -36
  78. /package/dist/{plugin → crawler}/addon/decodo/options.cjs +0 -0
  79. /package/dist/{plugin → crawler}/addon/decodo/options.js +0 -0
  80. /package/dist/{plugin → crawler}/addon/decodo/types.cjs +0 -0
  81. /package/dist/{plugin → crawler}/addon/decodo/types.js +0 -0
  82. /package/dist/{plugin → crawler}/addon/oxylabs/index.cjs +0 -0
  83. /package/dist/{plugin → crawler}/addon/oxylabs/index.js +0 -0
  84. /package/dist/{plugin → crawler}/addon/oxylabs/options.cjs +0 -0
  85. /package/dist/{plugin → crawler}/addon/oxylabs/options.js +0 -0
  86. /package/dist/{plugin → crawler}/addon/oxylabs/types.cjs +0 -0
  87. /package/dist/{plugin → crawler}/addon/oxylabs/types.js +0 -0
  88. /package/dist/{plugin → crawler}/scraper.cjs +0 -0
  89. /package/dist/{plugin → crawler}/scraper.js +0 -0
@@ -1,5 +1,5 @@
1
- const _mod_oeicap = require('../plugin/crawler.cjs');
2
- exports.Crawler = _mod_oeicap.Crawler;;
3
- const _mod_m779ll = require('../plugin/crawler-options.cjs');
4
- exports.CrawlerOptions = _mod_m779ll.CrawlerOptions;
5
- exports.Domain = _mod_m779ll.Domain;;
1
+ const _mod_398eir = require('../crawler/crawler.cjs');
2
+ exports.Crawler = _mod_398eir.Crawler;;
3
+ const _mod_m4xc57 = require('../crawler/crawler-options.cjs');
4
+ exports.CrawlerOptions = _mod_m4xc57.CrawlerOptions;
5
+ exports.Domain = _mod_m4xc57.Domain;;
@@ -1,2 +1,2 @@
1
- export { Crawler } from '../plugin/crawler.js';
2
- export { CrawlerOptions, Domain } from '../plugin/crawler-options.js';
1
+ export { Crawler } from '../crawler/crawler.js';
2
+ export { CrawlerOptions, Domain } from '../crawler/crawler-options.js';
package/dist/index.cjs CHANGED
@@ -1,27 +1,30 @@
1
- const _mod_0yc999 = require('./core/rezo.cjs');
2
- exports.Rezo = _mod_0yc999.Rezo;
3
- exports.createRezoInstance = _mod_0yc999.createRezoInstance;
4
- exports.createDefaultInstance = _mod_0yc999.createDefaultInstance;;
5
- const _mod_mgwmh3 = require('./errors/rezo-error.cjs');
6
- exports.RezoError = _mod_mgwmh3.RezoError;
7
- exports.RezoErrorCode = _mod_mgwmh3.RezoErrorCode;;
8
- const _mod_sms50x = require('./utils/headers.cjs');
9
- exports.RezoHeaders = _mod_sms50x.RezoHeaders;;
10
- const _mod_ak9q56 = require('./utils/form-data.cjs');
11
- exports.RezoFormData = _mod_ak9q56.RezoFormData;;
12
- const _mod_q6v2w1 = require('./utils/cookies.cjs');
13
- exports.RezoCookieJar = _mod_q6v2w1.RezoCookieJar;
14
- exports.Cookie = _mod_q6v2w1.Cookie;;
15
- const _mod_rlboga = require('./core/hooks.cjs');
16
- exports.createDefaultHooks = _mod_rlboga.createDefaultHooks;
17
- exports.mergeHooks = _mod_rlboga.mergeHooks;;
18
- const _mod_5cnq33 = require('./proxy/manager.cjs');
19
- exports.ProxyManager = _mod_5cnq33.ProxyManager;;
20
- const _mod_03guke = require('./queue/index.cjs');
21
- exports.RezoQueue = _mod_03guke.RezoQueue;
22
- exports.HttpQueue = _mod_03guke.HttpQueue;
23
- exports.Priority = _mod_03guke.Priority;
24
- exports.HttpMethodPriority = _mod_03guke.HttpMethodPriority;;
1
+ const _mod_y77uk1 = require('./core/rezo.cjs');
2
+ exports.Rezo = _mod_y77uk1.Rezo;
3
+ exports.createRezoInstance = _mod_y77uk1.createRezoInstance;
4
+ exports.createDefaultInstance = _mod_y77uk1.createDefaultInstance;;
5
+ const _mod_dc3jgu = require('./errors/rezo-error.cjs');
6
+ exports.RezoError = _mod_dc3jgu.RezoError;
7
+ exports.RezoErrorCode = _mod_dc3jgu.RezoErrorCode;;
8
+ const _mod_o16xti = require('./utils/headers.cjs');
9
+ exports.RezoHeaders = _mod_o16xti.RezoHeaders;;
10
+ const _mod_y43k9y = require('./utils/form-data.cjs');
11
+ exports.RezoFormData = _mod_y43k9y.RezoFormData;;
12
+ const _mod_n8l01e = require('./utils/cookies.cjs');
13
+ exports.RezoCookieJar = _mod_n8l01e.RezoCookieJar;
14
+ exports.Cookie = _mod_n8l01e.Cookie;;
15
+ const _mod_3ypli0 = require('./utils/curl.cjs');
16
+ exports.toCurl = _mod_3ypli0.toCurl;
17
+ exports.fromCurl = _mod_3ypli0.fromCurl;;
18
+ const _mod_1mlx0a = require('./core/hooks.cjs');
19
+ exports.createDefaultHooks = _mod_1mlx0a.createDefaultHooks;
20
+ exports.mergeHooks = _mod_1mlx0a.mergeHooks;;
21
+ const _mod_xo1ifa = require('./proxy/manager.cjs');
22
+ exports.ProxyManager = _mod_xo1ifa.ProxyManager;;
23
+ const _mod_77x7bf = require('./queue/index.cjs');
24
+ exports.RezoQueue = _mod_77x7bf.RezoQueue;
25
+ exports.HttpQueue = _mod_77x7bf.HttpQueue;
26
+ exports.Priority = _mod_77x7bf.Priority;
27
+ exports.HttpMethodPriority = _mod_77x7bf.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;