rezo 1.0.2 → 1.0.4
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/README.md +261 -0
- package/dist/adapters/curl.cjs +47 -1
- package/dist/adapters/curl.js +47 -1
- package/dist/adapters/entries/curl.cjs +31 -4
- package/dist/adapters/entries/curl.d.ts +2576 -847
- package/dist/adapters/entries/curl.js +29 -2
- package/dist/adapters/entries/fetch.cjs +31 -2
- package/dist/adapters/entries/fetch.d.ts +1753 -15
- package/dist/adapters/entries/fetch.js +29 -1
- package/dist/adapters/entries/http.cjs +31 -2
- package/dist/adapters/entries/http.d.ts +1774 -14
- package/dist/adapters/entries/http.js +29 -1
- package/dist/adapters/entries/http2.cjs +31 -4
- package/dist/adapters/entries/http2.d.ts +1748 -19
- package/dist/adapters/entries/http2.js +29 -2
- package/dist/adapters/entries/react-native.cjs +31 -2
- package/dist/adapters/entries/react-native.d.ts +1753 -14
- package/dist/adapters/entries/react-native.js +29 -1
- package/dist/adapters/entries/xhr.cjs +31 -2
- package/dist/adapters/entries/xhr.d.ts +1753 -15
- package/dist/adapters/entries/xhr.js +29 -1
- package/dist/adapters/fetch.cjs +24 -20
- package/dist/adapters/fetch.js +24 -20
- package/dist/adapters/http.cjs +69 -19
- package/dist/adapters/http.js +69 -19
- package/dist/adapters/http2.cjs +69 -19
- package/dist/adapters/http2.js +69 -19
- package/dist/adapters/index.cjs +6 -6
- package/dist/cache/index.cjs +13 -13
- package/dist/core/hooks.cjs +16 -0
- package/dist/core/hooks.js +16 -0
- package/dist/core/rezo.cjs +23 -1
- package/dist/core/rezo.js +23 -1
- package/dist/crawler.d.ts +528 -5
- package/dist/entries/crawler.cjs +5 -5
- package/dist/index.cjs +18 -16
- package/dist/index.d.ts +564 -5
- package/dist/index.js +1 -0
- package/dist/platform/browser.cjs +24 -2
- package/dist/platform/browser.d.ts +672 -10
- package/dist/platform/browser.js +24 -2
- package/dist/platform/bun.cjs +24 -2
- package/dist/platform/bun.d.ts +672 -10
- package/dist/platform/bun.js +24 -2
- package/dist/platform/deno.cjs +24 -2
- package/dist/platform/deno.d.ts +672 -10
- package/dist/platform/deno.js +24 -2
- package/dist/platform/node.cjs +24 -2
- package/dist/platform/node.d.ts +672 -10
- package/dist/platform/node.js +24 -2
- package/dist/platform/react-native.cjs +24 -2
- package/dist/platform/react-native.d.ts +672 -10
- package/dist/platform/react-native.js +24 -2
- package/dist/platform/worker.cjs +24 -2
- package/dist/platform/worker.d.ts +672 -10
- package/dist/platform/worker.js +24 -2
- package/dist/plugin/index.cjs +36 -36
- package/dist/proxy/index.cjs +2 -0
- package/dist/proxy/index.js +1 -0
- package/dist/proxy/manager.cjs +446 -0
- package/dist/proxy/manager.js +444 -0
- package/dist/utils/http-config.cjs +14 -3
- package/dist/utils/http-config.js +14 -3
- package/package.json +19 -4
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
function generateProxyId() {
|
|
2
|
+
return `proxy_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export class ProxyManager {
|
|
6
|
+
config;
|
|
7
|
+
states = new Map;
|
|
8
|
+
currentIndex = 0;
|
|
9
|
+
currentProxyRequests = 0;
|
|
10
|
+
lastSelectedProxy = null;
|
|
11
|
+
cooldownTimers = new Map;
|
|
12
|
+
_totalRequests = 0;
|
|
13
|
+
_totalSuccesses = 0;
|
|
14
|
+
_totalFailures = 0;
|
|
15
|
+
hooks = {
|
|
16
|
+
beforeProxySelect: [],
|
|
17
|
+
afterProxySelect: [],
|
|
18
|
+
beforeProxyError: [],
|
|
19
|
+
afterProxyError: [],
|
|
20
|
+
beforeProxyDisable: [],
|
|
21
|
+
afterProxyDisable: [],
|
|
22
|
+
afterProxyRotate: [],
|
|
23
|
+
afterProxyEnable: []
|
|
24
|
+
};
|
|
25
|
+
constructor(config) {
|
|
26
|
+
this.config = {
|
|
27
|
+
failWithoutProxy: true,
|
|
28
|
+
autoDisableDeadProxies: false,
|
|
29
|
+
maxFailures: 3,
|
|
30
|
+
retryWithNextProxy: false,
|
|
31
|
+
maxProxyRetries: 3,
|
|
32
|
+
...config
|
|
33
|
+
};
|
|
34
|
+
for (const proxy of this.config.proxies) {
|
|
35
|
+
if (!proxy.id) {
|
|
36
|
+
proxy.id = generateProxyId();
|
|
37
|
+
}
|
|
38
|
+
this.states.set(proxy.id, this.createInitialState(proxy));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
createInitialState(proxy) {
|
|
42
|
+
return {
|
|
43
|
+
proxy,
|
|
44
|
+
requestCount: 0,
|
|
45
|
+
failureCount: 0,
|
|
46
|
+
successCount: 0,
|
|
47
|
+
totalFailures: 0,
|
|
48
|
+
isActive: true
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
shouldProxy(url) {
|
|
52
|
+
const { whitelist, blacklist } = this.config;
|
|
53
|
+
if (whitelist && whitelist.length > 0) {
|
|
54
|
+
const matches = whitelist.some((pattern) => this.matchPattern(pattern, url));
|
|
55
|
+
if (!matches) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (blacklist && blacklist.length > 0) {
|
|
60
|
+
const matches = blacklist.some((pattern) => this.matchPattern(pattern, url));
|
|
61
|
+
if (matches) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
matchPattern(pattern, url) {
|
|
68
|
+
if (pattern instanceof RegExp) {
|
|
69
|
+
return pattern.test(url);
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
const urlObj = new URL(url);
|
|
73
|
+
const hostname = urlObj.hostname;
|
|
74
|
+
if (hostname === pattern) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
if (hostname.endsWith("." + pattern)) {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
if (pattern.startsWith("*.")) {
|
|
81
|
+
const domain = pattern.slice(2);
|
|
82
|
+
if (hostname === domain || hostname.endsWith("." + domain)) {
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return false;
|
|
87
|
+
} catch {
|
|
88
|
+
return url.includes(pattern);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
getActive() {
|
|
92
|
+
this.processExpiredCooldowns();
|
|
93
|
+
return Array.from(this.states.values()).filter((state) => state.isActive).map((state) => state.proxy);
|
|
94
|
+
}
|
|
95
|
+
getDisabled() {
|
|
96
|
+
return Array.from(this.states.values()).filter((state) => !state.isActive && !state.reenableAt).map((state) => state.proxy);
|
|
97
|
+
}
|
|
98
|
+
getCooldown() {
|
|
99
|
+
const now = Date.now();
|
|
100
|
+
return Array.from(this.states.values()).filter((state) => !state.isActive && state.reenableAt && state.reenableAt > now).map((state) => state.proxy);
|
|
101
|
+
}
|
|
102
|
+
processExpiredCooldowns() {
|
|
103
|
+
const now = Date.now();
|
|
104
|
+
for (const state of this.states.values()) {
|
|
105
|
+
if (!state.isActive && state.reenableAt && state.reenableAt <= now) {
|
|
106
|
+
this.enableProxy(state.proxy, "cooldown-expired");
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
next(url) {
|
|
111
|
+
this._totalRequests++;
|
|
112
|
+
const activeProxies = this.getActive();
|
|
113
|
+
this.runBeforeProxySelectHooksSync({
|
|
114
|
+
url,
|
|
115
|
+
proxies: activeProxies,
|
|
116
|
+
isRetry: false,
|
|
117
|
+
retryCount: 0
|
|
118
|
+
});
|
|
119
|
+
if (!this.shouldProxy(url)) {
|
|
120
|
+
this.runAfterProxySelectHooksSync({
|
|
121
|
+
url,
|
|
122
|
+
proxy: null,
|
|
123
|
+
reason: this.config.blacklist?.some((p) => this.matchPattern(p, url)) ? "blacklist-match" : "whitelist-no-match"
|
|
124
|
+
});
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
if (activeProxies.length === 0) {
|
|
128
|
+
this.runAfterProxySelectHooksSync({
|
|
129
|
+
url,
|
|
130
|
+
proxy: null,
|
|
131
|
+
reason: "no-proxies-available"
|
|
132
|
+
});
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
const selected = this.selectProxy(activeProxies);
|
|
136
|
+
if (selected) {
|
|
137
|
+
const state = this.states.get(selected.id);
|
|
138
|
+
if (state) {
|
|
139
|
+
state.requestCount++;
|
|
140
|
+
if (this.config.rotation === "per-proxy-limit") {
|
|
141
|
+
const limit = this.config.limit;
|
|
142
|
+
if (state.requestCount >= limit) {
|
|
143
|
+
this.disableProxy(selected, "limit-reached");
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (this.lastSelectedProxy && this.lastSelectedProxy.id !== selected.id) {
|
|
148
|
+
this.runAfterProxyRotateHooks({
|
|
149
|
+
from: this.lastSelectedProxy,
|
|
150
|
+
to: selected,
|
|
151
|
+
reason: "scheduled"
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
this.lastSelectedProxy = selected;
|
|
155
|
+
}
|
|
156
|
+
this.runAfterProxySelectHooksSync({
|
|
157
|
+
url,
|
|
158
|
+
proxy: selected,
|
|
159
|
+
reason: selected ? "selected" : "no-proxies-available"
|
|
160
|
+
});
|
|
161
|
+
return selected;
|
|
162
|
+
}
|
|
163
|
+
select(url) {
|
|
164
|
+
this._totalRequests++;
|
|
165
|
+
if (!this.shouldProxy(url)) {
|
|
166
|
+
const { whitelist, blacklist } = this.config;
|
|
167
|
+
const reason = blacklist?.some((p) => this.matchPattern(p, url)) ? "blacklist-match" : "whitelist-no-match";
|
|
168
|
+
return { proxy: null, reason };
|
|
169
|
+
}
|
|
170
|
+
const activeProxies = this.getActive();
|
|
171
|
+
if (activeProxies.length === 0) {
|
|
172
|
+
return { proxy: null, reason: "no-proxies-available" };
|
|
173
|
+
}
|
|
174
|
+
const selected = this.selectProxy(activeProxies);
|
|
175
|
+
if (selected) {
|
|
176
|
+
const state = this.states.get(selected.id);
|
|
177
|
+
if (state) {
|
|
178
|
+
state.requestCount++;
|
|
179
|
+
if (this.config.rotation === "per-proxy-limit") {
|
|
180
|
+
const limit = this.config.limit;
|
|
181
|
+
if (state.requestCount >= limit) {
|
|
182
|
+
this.disableProxy(selected, "limit-reached");
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
this.lastSelectedProxy = selected;
|
|
187
|
+
return { proxy: selected, reason: "selected" };
|
|
188
|
+
}
|
|
189
|
+
return { proxy: null, reason: "no-proxies-available" };
|
|
190
|
+
}
|
|
191
|
+
selectProxy(activeProxies) {
|
|
192
|
+
if (activeProxies.length === 0) {
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
const rotation = this.config.rotation;
|
|
196
|
+
if (rotation === "random") {
|
|
197
|
+
const index = Math.floor(Math.random() * activeProxies.length);
|
|
198
|
+
return activeProxies[index];
|
|
199
|
+
}
|
|
200
|
+
if (rotation === "sequential") {
|
|
201
|
+
const requestsPerProxy = this.config.requestsPerProxy ?? 1;
|
|
202
|
+
if (this.currentProxyRequests >= requestsPerProxy) {
|
|
203
|
+
this.currentIndex = (this.currentIndex + 1) % activeProxies.length;
|
|
204
|
+
this.currentProxyRequests = 0;
|
|
205
|
+
}
|
|
206
|
+
if (this.currentIndex >= activeProxies.length) {
|
|
207
|
+
this.currentIndex = 0;
|
|
208
|
+
}
|
|
209
|
+
this.currentProxyRequests++;
|
|
210
|
+
return activeProxies[this.currentIndex];
|
|
211
|
+
}
|
|
212
|
+
if (rotation === "per-proxy-limit") {
|
|
213
|
+
for (const proxy of activeProxies) {
|
|
214
|
+
const state = this.states.get(proxy.id);
|
|
215
|
+
if (state && state.isActive) {
|
|
216
|
+
return proxy;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return null;
|
|
220
|
+
}
|
|
221
|
+
return activeProxies[0];
|
|
222
|
+
}
|
|
223
|
+
reportSuccess(proxy) {
|
|
224
|
+
this._totalSuccesses++;
|
|
225
|
+
const state = this.states.get(proxy.id);
|
|
226
|
+
if (state) {
|
|
227
|
+
state.successCount++;
|
|
228
|
+
state.failureCount = 0;
|
|
229
|
+
state.lastSuccessAt = Date.now();
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
reportFailure(proxy, error, url) {
|
|
233
|
+
this._totalFailures++;
|
|
234
|
+
const state = this.states.get(proxy.id);
|
|
235
|
+
if (!state)
|
|
236
|
+
return;
|
|
237
|
+
const willBeDisabled = !!(this.config.autoDisableDeadProxies && state.failureCount + 1 >= (this.config.maxFailures ?? 3));
|
|
238
|
+
this.runBeforeProxyErrorHooksSync({
|
|
239
|
+
proxy,
|
|
240
|
+
error,
|
|
241
|
+
url: url || "",
|
|
242
|
+
failureCount: state.failureCount + 1,
|
|
243
|
+
willBeDisabled
|
|
244
|
+
});
|
|
245
|
+
state.failureCount++;
|
|
246
|
+
state.totalFailures++;
|
|
247
|
+
state.lastFailureAt = Date.now();
|
|
248
|
+
state.lastError = error.message;
|
|
249
|
+
let action = "continue";
|
|
250
|
+
if (this.config.autoDisableDeadProxies) {
|
|
251
|
+
const maxFailures = this.config.maxFailures ?? 3;
|
|
252
|
+
if (state.failureCount >= maxFailures) {
|
|
253
|
+
this.disableProxy(proxy, "dead");
|
|
254
|
+
action = "disabled";
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
this.runAfterProxyErrorHooksSync({
|
|
258
|
+
proxy,
|
|
259
|
+
error,
|
|
260
|
+
action
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
disableProxy(proxy, reason = "manual") {
|
|
264
|
+
const state = this.states.get(proxy.id);
|
|
265
|
+
if (!state || !state.isActive)
|
|
266
|
+
return;
|
|
267
|
+
state.isActive = false;
|
|
268
|
+
state.disabledReason = reason;
|
|
269
|
+
state.disabledAt = Date.now();
|
|
270
|
+
const { cooldown } = this.config;
|
|
271
|
+
let hasCooldown = false;
|
|
272
|
+
let reenableAt;
|
|
273
|
+
if (cooldown?.enabled && cooldown.durationMs > 0) {
|
|
274
|
+
hasCooldown = true;
|
|
275
|
+
reenableAt = Date.now() + cooldown.durationMs;
|
|
276
|
+
state.reenableAt = reenableAt;
|
|
277
|
+
const timerId = setTimeout(() => {
|
|
278
|
+
this.enableProxy(proxy, "cooldown-expired");
|
|
279
|
+
this.cooldownTimers.delete(proxy.id);
|
|
280
|
+
}, cooldown.durationMs);
|
|
281
|
+
this.cooldownTimers.set(proxy.id, timerId);
|
|
282
|
+
}
|
|
283
|
+
this.runAfterProxyDisableHooks({
|
|
284
|
+
proxy,
|
|
285
|
+
reason,
|
|
286
|
+
hasCooldown,
|
|
287
|
+
reenableAt
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
enableProxy(proxy, reason = "manual") {
|
|
291
|
+
const state = this.states.get(proxy.id);
|
|
292
|
+
if (!state || state.isActive)
|
|
293
|
+
return;
|
|
294
|
+
state.isActive = true;
|
|
295
|
+
state.failureCount = 0;
|
|
296
|
+
state.disabledReason = undefined;
|
|
297
|
+
state.disabledAt = undefined;
|
|
298
|
+
state.reenableAt = undefined;
|
|
299
|
+
const timerId = this.cooldownTimers.get(proxy.id);
|
|
300
|
+
if (timerId) {
|
|
301
|
+
clearTimeout(timerId);
|
|
302
|
+
this.cooldownTimers.delete(proxy.id);
|
|
303
|
+
}
|
|
304
|
+
this.runAfterProxyEnableHooks({
|
|
305
|
+
proxy,
|
|
306
|
+
reason
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
add(proxies) {
|
|
310
|
+
const toAdd = Array.isArray(proxies) ? proxies : [proxies];
|
|
311
|
+
for (const proxy of toAdd) {
|
|
312
|
+
if (!proxy.id) {
|
|
313
|
+
proxy.id = generateProxyId();
|
|
314
|
+
}
|
|
315
|
+
if (!this.states.has(proxy.id)) {
|
|
316
|
+
this.states.set(proxy.id, this.createInitialState(proxy));
|
|
317
|
+
this.config.proxies.push(proxy);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
remove(proxies) {
|
|
322
|
+
const toRemove = Array.isArray(proxies) ? proxies : [proxies];
|
|
323
|
+
for (const proxy of toRemove) {
|
|
324
|
+
if (proxy.id) {
|
|
325
|
+
const timerId = this.cooldownTimers.get(proxy.id);
|
|
326
|
+
if (timerId) {
|
|
327
|
+
clearTimeout(timerId);
|
|
328
|
+
this.cooldownTimers.delete(proxy.id);
|
|
329
|
+
}
|
|
330
|
+
this.states.delete(proxy.id);
|
|
331
|
+
const index = this.config.proxies.findIndex((p) => p.id === proxy.id);
|
|
332
|
+
if (index !== -1) {
|
|
333
|
+
this.config.proxies.splice(index, 1);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
reset() {
|
|
339
|
+
for (const timerId of this.cooldownTimers.values()) {
|
|
340
|
+
clearTimeout(timerId);
|
|
341
|
+
}
|
|
342
|
+
this.cooldownTimers.clear();
|
|
343
|
+
for (const state of this.states.values()) {
|
|
344
|
+
state.requestCount = 0;
|
|
345
|
+
state.failureCount = 0;
|
|
346
|
+
state.isActive = true;
|
|
347
|
+
state.disabledReason = undefined;
|
|
348
|
+
state.disabledAt = undefined;
|
|
349
|
+
state.reenableAt = undefined;
|
|
350
|
+
}
|
|
351
|
+
this.currentIndex = 0;
|
|
352
|
+
this.currentProxyRequests = 0;
|
|
353
|
+
this.lastSelectedProxy = null;
|
|
354
|
+
}
|
|
355
|
+
getStatus() {
|
|
356
|
+
this.processExpiredCooldowns();
|
|
357
|
+
return {
|
|
358
|
+
active: this.getActive(),
|
|
359
|
+
disabled: this.getDisabled(),
|
|
360
|
+
cooldown: this.getCooldown(),
|
|
361
|
+
total: this.states.size,
|
|
362
|
+
rotation: this.config.rotation,
|
|
363
|
+
totalRequests: this._totalRequests,
|
|
364
|
+
totalSuccesses: this._totalSuccesses,
|
|
365
|
+
totalFailures: this._totalFailures
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
getProxyState(proxy) {
|
|
369
|
+
return this.states.get(proxy.id);
|
|
370
|
+
}
|
|
371
|
+
hasAvailableProxies() {
|
|
372
|
+
return this.getActive().length > 0;
|
|
373
|
+
}
|
|
374
|
+
destroy() {
|
|
375
|
+
for (const timerId of this.cooldownTimers.values()) {
|
|
376
|
+
clearTimeout(timerId);
|
|
377
|
+
}
|
|
378
|
+
this.cooldownTimers.clear();
|
|
379
|
+
this.states.clear();
|
|
380
|
+
}
|
|
381
|
+
runBeforeProxySelectHooksSync(context) {
|
|
382
|
+
for (const hook of this.hooks.beforeProxySelect) {
|
|
383
|
+
try {
|
|
384
|
+
hook(context);
|
|
385
|
+
} catch (error) {
|
|
386
|
+
console.error("[ProxyManager] beforeProxySelect hook error:", error);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
runAfterProxySelectHooksSync(context) {
|
|
391
|
+
for (const hook of this.hooks.afterProxySelect) {
|
|
392
|
+
try {
|
|
393
|
+
hook(context);
|
|
394
|
+
} catch (error) {
|
|
395
|
+
console.error("[ProxyManager] afterProxySelect hook error:", error);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
runBeforeProxyErrorHooksSync(context) {
|
|
400
|
+
for (const hook of this.hooks.beforeProxyError) {
|
|
401
|
+
try {
|
|
402
|
+
hook(context);
|
|
403
|
+
} catch (error) {
|
|
404
|
+
console.error("[ProxyManager] beforeProxyError hook error:", error);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
runAfterProxyErrorHooksSync(context) {
|
|
409
|
+
for (const hook of this.hooks.afterProxyError) {
|
|
410
|
+
try {
|
|
411
|
+
hook(context);
|
|
412
|
+
} catch (error) {
|
|
413
|
+
console.error("[ProxyManager] afterProxyError hook error:", error);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
runAfterProxyRotateHooks(context) {
|
|
418
|
+
for (const hook of this.hooks.afterProxyRotate) {
|
|
419
|
+
try {
|
|
420
|
+
hook(context);
|
|
421
|
+
} catch (error) {
|
|
422
|
+
console.error("[ProxyManager] afterProxyRotate hook error:", error);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
runAfterProxyDisableHooks(context) {
|
|
427
|
+
for (const hook of this.hooks.afterProxyDisable) {
|
|
428
|
+
try {
|
|
429
|
+
hook(context);
|
|
430
|
+
} catch (error) {
|
|
431
|
+
console.error("[ProxyManager] afterProxyDisable hook error:", error);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
runAfterProxyEnableHooks(context) {
|
|
436
|
+
for (const hook of this.hooks.afterProxyEnable) {
|
|
437
|
+
try {
|
|
438
|
+
hook(context);
|
|
439
|
+
} catch (error) {
|
|
440
|
+
console.error("[ProxyManager] afterProxyEnable hook error:", error);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
@@ -157,6 +157,10 @@ const ERROR_INFO = exports.ERROR_INFO = {
|
|
|
157
157
|
UNQ_PROXY_ERROR: {
|
|
158
158
|
code: -1047,
|
|
159
159
|
message: "Proxy Error: An unspecified error occurred while communicating with or through the proxy server."
|
|
160
|
+
},
|
|
161
|
+
UNQ_NO_PROXY_AVAILABLE: {
|
|
162
|
+
code: -1050,
|
|
163
|
+
message: "No Proxy Available: All proxies in ProxyManager are exhausted, disabled, or the URL did not match whitelist/blacklist rules."
|
|
160
164
|
}
|
|
161
165
|
};
|
|
162
166
|
function setSignal() {
|
|
@@ -170,7 +174,7 @@ function setSignal() {
|
|
|
170
174
|
this.signal = controller.signal;
|
|
171
175
|
}
|
|
172
176
|
}
|
|
173
|
-
async function getDefaultConfig(config = {}) {
|
|
177
|
+
async function getDefaultConfig(config = {}, proxyManager) {
|
|
174
178
|
const curl = await checkCurl();
|
|
175
179
|
return {
|
|
176
180
|
useCurl: config.curl === true,
|
|
@@ -191,7 +195,8 @@ async function getDefaultConfig(config = {}) {
|
|
|
191
195
|
http2: config.http2 === true,
|
|
192
196
|
hooks: config.hooks,
|
|
193
197
|
cookieFile: config.cookieFile,
|
|
194
|
-
encoding: config.encoding
|
|
198
|
+
encoding: config.encoding,
|
|
199
|
+
proxyManager: proxyManager || null
|
|
195
200
|
};
|
|
196
201
|
}
|
|
197
202
|
async function getFS() {
|
|
@@ -404,10 +409,16 @@ function prepareHTTPOptions(options, jar, addedOptions, config) {
|
|
|
404
409
|
if (options.sessionId) {
|
|
405
410
|
fetchOptions.sessionId = options.sessionId;
|
|
406
411
|
}
|
|
412
|
+
let resolvedProxyManager = null;
|
|
413
|
+
const pm = addedOptions.defaultOptions.proxyManager;
|
|
414
|
+
if (pm && options.useProxyManager !== false && !options.proxy) {
|
|
415
|
+
resolvedProxyManager = pm;
|
|
416
|
+
}
|
|
407
417
|
return {
|
|
408
418
|
fetchOptions,
|
|
409
419
|
config,
|
|
410
|
-
options
|
|
420
|
+
options,
|
|
421
|
+
proxyManager: resolvedProxyManager
|
|
411
422
|
};
|
|
412
423
|
}
|
|
413
424
|
function buildHeaders(headers) {
|
|
@@ -157,6 +157,10 @@ export const ERROR_INFO = {
|
|
|
157
157
|
UNQ_PROXY_ERROR: {
|
|
158
158
|
code: -1047,
|
|
159
159
|
message: "Proxy Error: An unspecified error occurred while communicating with or through the proxy server."
|
|
160
|
+
},
|
|
161
|
+
UNQ_NO_PROXY_AVAILABLE: {
|
|
162
|
+
code: -1050,
|
|
163
|
+
message: "No Proxy Available: All proxies in ProxyManager are exhausted, disabled, or the URL did not match whitelist/blacklist rules."
|
|
160
164
|
}
|
|
161
165
|
};
|
|
162
166
|
function setSignal() {
|
|
@@ -170,7 +174,7 @@ function setSignal() {
|
|
|
170
174
|
this.signal = controller.signal;
|
|
171
175
|
}
|
|
172
176
|
}
|
|
173
|
-
export async function getDefaultConfig(config = {}) {
|
|
177
|
+
export async function getDefaultConfig(config = {}, proxyManager) {
|
|
174
178
|
const curl = await checkCurl();
|
|
175
179
|
return {
|
|
176
180
|
useCurl: config.curl === true,
|
|
@@ -191,7 +195,8 @@ export async function getDefaultConfig(config = {}) {
|
|
|
191
195
|
http2: config.http2 === true,
|
|
192
196
|
hooks: config.hooks,
|
|
193
197
|
cookieFile: config.cookieFile,
|
|
194
|
-
encoding: config.encoding
|
|
198
|
+
encoding: config.encoding,
|
|
199
|
+
proxyManager: proxyManager || null
|
|
195
200
|
};
|
|
196
201
|
}
|
|
197
202
|
export async function getFS() {
|
|
@@ -404,10 +409,16 @@ export function prepareHTTPOptions(options, jar, addedOptions, config) {
|
|
|
404
409
|
if (options.sessionId) {
|
|
405
410
|
fetchOptions.sessionId = options.sessionId;
|
|
406
411
|
}
|
|
412
|
+
let resolvedProxyManager = null;
|
|
413
|
+
const pm = addedOptions.defaultOptions.proxyManager;
|
|
414
|
+
if (pm && options.useProxyManager !== false && !options.proxy) {
|
|
415
|
+
resolvedProxyManager = pm;
|
|
416
|
+
}
|
|
407
417
|
return {
|
|
408
418
|
fetchOptions,
|
|
409
419
|
config,
|
|
410
|
-
options
|
|
420
|
+
options,
|
|
421
|
+
proxyManager: resolvedProxyManager
|
|
411
422
|
};
|
|
412
423
|
}
|
|
413
424
|
function buildHeaders(headers) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rezo",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Lightning-fast, enterprise-grade HTTP client for modern JavaScript. Full HTTP/2 support, intelligent cookie management, multiple adapters (HTTP, Fetch, cURL, XHR), streaming, proxy support (HTTP/HTTPS/SOCKS), and cross-environment compatibility.",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -118,9 +118,24 @@
|
|
|
118
118
|
},
|
|
119
119
|
"exports": {
|
|
120
120
|
".": {
|
|
121
|
-
"types":
|
|
122
|
-
|
|
123
|
-
|
|
121
|
+
"types": {
|
|
122
|
+
"require": "./dist/index.d.ts",
|
|
123
|
+
"default": "./dist/index.d.ts"
|
|
124
|
+
},
|
|
125
|
+
"react-native": {
|
|
126
|
+
"types": "./dist/platform/react-native.d.ts",
|
|
127
|
+
"require": "./dist/platform/react-native.cjs",
|
|
128
|
+
"default": "./dist/platform/react-native.js"
|
|
129
|
+
},
|
|
130
|
+
"browser": {
|
|
131
|
+
"types": "./dist/platform/browser.d.ts",
|
|
132
|
+
"require": "./dist/platform/browser.cjs",
|
|
133
|
+
"default": "./dist/platform/browser.js"
|
|
134
|
+
},
|
|
135
|
+
"default": {
|
|
136
|
+
"require": "./dist/index.cjs",
|
|
137
|
+
"default": "./dist/index.js"
|
|
138
|
+
}
|
|
124
139
|
},
|
|
125
140
|
"./platform/node": {
|
|
126
141
|
"types": "./dist/platform/node.d.ts",
|