arn-browser 0.1.2 → 0.1.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arn-browser",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "A lightweight, browser autmation helper.",
5
5
  "main": "src/index.js",
6
6
  "types": "src/index.d.ts",
@@ -64,6 +64,8 @@ export interface ProxyServerOptions {
64
64
  debug?: boolean;
65
65
  /** Track proxy usage statistics (default: true) */
66
66
  proxy_stats?: boolean;
67
+ /** Track hostname usage statistics (default: true) */
68
+ host_stats?: boolean;
67
69
  }
68
70
 
69
71
  /**
@@ -102,11 +104,17 @@ export interface ProxyServerController {
102
104
  /** The public IP of Proxy 2 */
103
105
  PROXY_2_IP: string | null;
104
106
 
107
+ /** Check if the proxy server is currently running */
108
+ isServerRunning: () => boolean;
109
+
105
110
  /** Gracefully closes the proxy server */
106
111
  closeServer: () => Promise<void>;
107
112
 
108
113
  /** Returns formatted statistics for all proxy channels */
109
114
  getProxyStats: () => Record<string, TrafficStats>;
115
+
116
+ /** Returns formatted statistics for hostnames per proxy channel */
117
+ getHostStats: () => Record<string, Record<string, number>>;
110
118
  }
111
119
 
112
120
  /**
@@ -178,6 +178,7 @@ export async function startProxyServer({
178
178
  ip2LocationKey = null,
179
179
  debug = false,
180
180
  proxy_stats = true,
181
+ host_stats = true,
181
182
  }) {
182
183
  // 1. Matchers
183
184
  const matchers = {
@@ -227,7 +228,16 @@ export async function startProxyServer({
227
228
  PROXY_1: { request: 0, Tx: 0, Rx: 0 },
228
229
  PROXY_2: { request: 0, Tx: 0, Rx: 0 },
229
230
  };
230
- const connectionMap = {};
231
+ // hostStatsMap is now categorized by proxy type
232
+ const hostStatsMap = {
233
+ DEFAULT_PROXY: {},
234
+ NO_PROXY: {},
235
+ PROXY_1: {},
236
+ PROXY_2: {},
237
+ };
238
+
239
+ const connectionMap = {}; // Maps connectionId -> { type: "..." }
240
+ let serverRunning = false;
231
241
 
232
242
  // 6. Server
233
243
  const server = new ProxyChain.Server({
@@ -235,42 +245,61 @@ export async function startProxyServer({
235
245
  host: "127.0.0.1",
236
246
  verbose: debug,
237
247
  prepareRequestFunction: ({ hostname, connectionId }) => {
238
- // A. Direct (Force NO_PROXY)
248
+ let proxyType = "DEFAULT_PROXY";
249
+ let upstreamUrl = upstreamProxies.default;
250
+ let isCustomResponse = false;
251
+ let customResponseData = null;
252
+
253
+ // Logic to determine Proxy Type
239
254
  if (matchers.noProxy(hostname)) {
240
- connectionMap[connectionId] = { type: "NO_PROXY" };
241
- return { upstreamProxyUrl: null, requestAuthentication: false };
255
+ // A. Direct
256
+ proxyType = "NO_PROXY";
257
+ upstreamUrl = null;
258
+ } else if (matchers.proxy1(hostname) && upstreamProxies.p1) {
259
+ // C1. Proxy 1
260
+ proxyType = "PROXY_1";
261
+ upstreamUrl = upstreamProxies.p1;
262
+ } else if (matchers.proxy2(hostname) && upstreamProxies.p2) {
263
+ // C2. Proxy 2
264
+ proxyType = "PROXY_2";
265
+ upstreamUrl = upstreamProxies.p2;
242
266
  }
243
267
 
244
- // B. IP Check Interception (ip.bablosoft.com)
268
+ // B. IP Check Interception (Overrules standard routing for specific domain)
245
269
  if (hostname === "ip.bablosoft.com") {
270
+ isCustomResponse = true;
271
+ // Inherit the proxyType determined above to fetch the correct IP details
272
+ // (e.g. if it matched PROXY_1 matchers, we show PROXY_1 IP)
246
273
  let displayedIP;
247
-
248
- if (matchers.proxy1(hostname)) displayedIP = p1Details?.ip;
249
- else if (matchers.proxy2(hostname)) displayedIP = p2Details?.ip;
250
- else displayedIP = defaultDetails?.ip; // Uses Default (or Local fallback)
251
-
252
- return {
253
- customResponseFunction: () => ({
254
- statusCode: 200,
255
- headers: { "Content-Type": "text/plain", Connection: "close" },
256
- body: displayedIP || "Unknown IP",
257
- }),
274
+ if (proxyType === "PROXY_1") displayedIP = p1Details?.ip;
275
+ else if (proxyType === "PROXY_2") displayedIP = p2Details?.ip;
276
+ else if (proxyType === "NO_PROXY") displayedIP = "127.0.0.1";
277
+ else displayedIP = defaultDetails?.ip;
278
+
279
+ customResponseData = {
280
+ statusCode: 200,
281
+ headers: { "Content-Type": "text/plain", Connection: "close" },
282
+ body: displayedIP || "Unknown IP",
258
283
  };
259
284
  }
260
285
 
261
- // C. Routing
262
- if (matchers.proxy1(hostname) && upstreamProxies.p1) {
263
- connectionMap[connectionId] = { type: "PROXY_1" };
264
- return { upstreamProxyUrl: upstreamProxies.p1 };
286
+ // Record Stats
287
+ connectionMap[connectionId] = { type: proxyType };
288
+ if (host_stats && hostname) {
289
+ // Ensure the type exists in map (it should, but safety first)
290
+ if (!hostStatsMap[proxyType]) hostStatsMap[proxyType] = {};
291
+ hostStatsMap[proxyType][hostname] = (hostStatsMap[proxyType][hostname] || 0) + 1;
265
292
  }
266
- if (matchers.proxy2(hostname) && upstreamProxies.p2) {
267
- connectionMap[connectionId] = { type: "PROXY_2" };
268
- return { upstreamProxyUrl: upstreamProxies.p2 };
293
+
294
+ // Return Decision
295
+ if (isCustomResponse) {
296
+ return { customResponseFunction: () => customResponseData };
269
297
  }
270
298
 
271
- // D. Default
272
- connectionMap[connectionId] = { type: "DEFAULT_PROXY" };
273
- return { upstreamProxyUrl: upstreamProxies.default };
299
+ return {
300
+ upstreamProxyUrl: upstreamUrl,
301
+ requestAuthentication: false, // Auto-handle upstream auth via URL
302
+ };
274
303
  },
275
304
  });
276
305
 
@@ -289,6 +318,7 @@ export async function startProxyServer({
289
318
 
290
319
  try {
291
320
  await server.listen();
321
+ serverRunning = true;
292
322
  console.log(`✅ Local Proxy Started: http://127.0.0.1:${selectedPort}`);
293
323
  } catch (err) {
294
324
  console.error("❌ Failed to start proxy server:", err);
@@ -297,6 +327,37 @@ export async function startProxyServer({
297
327
 
298
328
  const formatBytes = (bytes) => (bytes / 1024 / 1024).toFixed(2);
299
329
 
330
+ const getProxyStatsFormatted = () => {
331
+ const formatted = {};
332
+ for (const [key, val] of Object.entries(stats)) {
333
+ formatted[key] = {
334
+ req: val.request,
335
+ Tx: formatBytes(val.Tx) + " MB",
336
+ Rx: formatBytes(val.Rx) + " MB",
337
+ };
338
+ }
339
+ return formatted;
340
+ };
341
+
342
+ const getHostStatsFormatted = () => {
343
+ const result = {};
344
+ // Iterate over each proxy category
345
+ for (const [type, hosts] of Object.entries(hostStatsMap)) {
346
+ const sortedHosts = Object.entries(hosts)
347
+ .sort((a, b) => b[1] - a[1]) // Sort by count descending
348
+ .reduce((acc, [host, count]) => {
349
+ acc[host] = count;
350
+ return acc;
351
+ }, {});
352
+
353
+ // Only include categories that have traffic
354
+ if (Object.keys(sortedHosts).length > 0) {
355
+ result[type] = sortedHosts;
356
+ }
357
+ }
358
+ return result;
359
+ };
360
+
300
361
  // 7. Return Controller
301
362
  return {
302
363
  port: selectedPort,
@@ -318,20 +379,24 @@ export async function startProxyServer({
318
379
  PROXY_1_IP: p1Details?.ip || null,
319
380
  PROXY_2_IP: p2Details?.ip || null,
320
381
 
382
+ isServerRunning: () => serverRunning,
383
+
321
384
  closeServer: async () => {
322
385
  await server.close(true);
323
- console.log("🔒 Proxy server closed.");
324
- },
325
- getProxyStats: () => {
326
- const formatted = {};
327
- for (const [key, val] of Object.entries(stats)) {
328
- formatted[key] = {
329
- req: val.request,
330
- Tx: formatBytes(val.Tx) + " MB",
331
- Rx: formatBytes(val.Rx) + " MB",
332
- };
386
+ serverRunning = false;
387
+
388
+ // Auto console.log stats on close
389
+ if (proxy_stats) {
390
+ console.log("📊 Proxy Stats:", getProxyStatsFormatted());
391
+ }
392
+ if (host_stats) {
393
+ console.log("🌐 Host Stats:", getHostStatsFormatted());
333
394
  }
334
- return formatted;
395
+
396
+ console.log("🔒 Proxy server closed.");
335
397
  },
398
+
399
+ getProxyStats: getProxyStatsFormatted,
400
+ getHostStats: getHostStatsFormatted,
336
401
  };
337
402
  }