arn-browser 0.1.15 → 0.1.16
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
|
@@ -32,6 +32,13 @@ export interface PwRouteOptions {
|
|
|
32
32
|
/** Enable caching for requests */
|
|
33
33
|
useCache?: boolean;
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Proxy for custom fetch requests (only used when useGot is true).
|
|
37
|
+
* String: "http://host:port", "socks5://user:pass@host:port"
|
|
38
|
+
* Object: { type, host, port, user, pass }
|
|
39
|
+
*/
|
|
40
|
+
proxy?: string | { type?: string; host: string; port: number; user?: string; pass?: string } | null;
|
|
41
|
+
|
|
35
42
|
/** Data object for Doublelist message interception (POST logic) */
|
|
36
43
|
m4w_send_on_post?: Record<string, any> | null;
|
|
37
44
|
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
import superagent from "superagent";
|
|
3
3
|
import { FiltersEngine, Request } from "@ghostery/adblocker";
|
|
4
4
|
import fetch from "node-fetch";
|
|
5
|
+
import { HttpsProxyAgent } from "https-proxy-agent";
|
|
6
|
+
import { SocksProxyAgent } from "socks-proxy-agent";
|
|
5
7
|
import NodeCache from "node-cache";
|
|
6
8
|
|
|
7
9
|
let AdBlockEngine;
|
|
@@ -37,6 +39,38 @@ export function pwCacheLogs(log_cache = globalCache, interval = 10) {
|
|
|
37
39
|
}
|
|
38
40
|
}
|
|
39
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Normalizes proxy input (string or object) into a URL string.
|
|
44
|
+
* Accepts:
|
|
45
|
+
* - String: "http://host:port", "socks5://user:pass@host:port", etc.
|
|
46
|
+
* - Object: { type, host, port, user, pass }
|
|
47
|
+
* @param {string|Object|null} proxy
|
|
48
|
+
* @returns {string|null} - Proxy URL string or null
|
|
49
|
+
*/
|
|
50
|
+
function formatProxyUrl(proxy) {
|
|
51
|
+
if (!proxy) return null;
|
|
52
|
+
if (typeof proxy === "string") return proxy;
|
|
53
|
+
if (typeof proxy === "object") {
|
|
54
|
+
const { type = "http", host, port, user, pass } = proxy;
|
|
55
|
+
const auth = user && pass ? `${user}:${pass}@` : "";
|
|
56
|
+
return `${type}://${auth}${host}:${port}`;
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Creates an HTTP agent for the given proxy URL.
|
|
63
|
+
* @param {string|null} proxyUrl
|
|
64
|
+
* @returns {Object|null} - HttpsProxyAgent or SocksProxyAgent instance
|
|
65
|
+
*/
|
|
66
|
+
function createProxyAgent(proxyUrl) {
|
|
67
|
+
if (!proxyUrl) return null;
|
|
68
|
+
if (proxyUrl.startsWith("socks")) {
|
|
69
|
+
return new SocksProxyAgent(proxyUrl);
|
|
70
|
+
}
|
|
71
|
+
return new HttpsProxyAgent(proxyUrl);
|
|
72
|
+
}
|
|
73
|
+
|
|
40
74
|
/**
|
|
41
75
|
* Function to fetch resources using Superagent library with optional caching.
|
|
42
76
|
* This mimics the browser's request but handles it in Node.js to allow caching or header manipulation.
|
|
@@ -46,9 +80,10 @@ export function pwCacheLogs(log_cache = globalCache, interval = 10) {
|
|
|
46
80
|
* @param {string} method - HTTP method (GET, POST, etc.)
|
|
47
81
|
* @param {boolean} useFullUrl - Whether to use the full URL as cache key or just origin+path
|
|
48
82
|
* @param {string|false} logger - Log level: "info" (success+error), "error" (errors only), false (no logs)
|
|
83
|
+
* @param {Object|null} proxyAgent - Proxy agent to use for the request
|
|
49
84
|
* @returns {Promise<Object>} - The response object containing status, headers, and body
|
|
50
85
|
*/
|
|
51
|
-
async function fetchWithClient(useCache, url, requestHeaders, method, useFullUrl, logger) {
|
|
86
|
+
async function fetchWithClient(useCache, url, requestHeaders, method, useFullUrl, logger, proxyAgent) {
|
|
52
87
|
// Determine the cache key based on configuration
|
|
53
88
|
let mainUrl = new URL(url).origin + new URL(url).pathname;
|
|
54
89
|
if (useFullUrl) {
|
|
@@ -67,18 +102,29 @@ async function fetchWithClient(useCache, url, requestHeaders, method, useFullUrl
|
|
|
67
102
|
try {
|
|
68
103
|
// Fetch the resource using superagent
|
|
69
104
|
// buffer(true) ensures we get the raw binary data (essential for images/fonts)
|
|
70
|
-
|
|
105
|
+
let request = superagent(method, url).set(requestHeaders).buffer(true);
|
|
106
|
+
|
|
107
|
+
// Apply proxy agent if provided
|
|
108
|
+
if (proxyAgent) {
|
|
109
|
+
request = request.agent(proxyAgent);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const response = await request;
|
|
71
113
|
|
|
72
114
|
// Determine the correct body type (Buffer for binary, text for others)
|
|
73
115
|
const responseBody = response.body instanceof Buffer ? response.body : response.text;
|
|
74
116
|
|
|
75
|
-
// Save to cache
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
117
|
+
// Save to cache only when caching is enabled
|
|
118
|
+
if (useCache) {
|
|
119
|
+
globalCache.set(mainUrl, {
|
|
120
|
+
status: response.status,
|
|
121
|
+
headers: response.headers,
|
|
122
|
+
body: responseBody,
|
|
123
|
+
});
|
|
124
|
+
if (logger === "info") console.log(`Success (cached): ${mainUrl}`);
|
|
125
|
+
} else {
|
|
126
|
+
if (logger === "info") console.log(`Success (not cached): ${mainUrl}`);
|
|
127
|
+
}
|
|
82
128
|
|
|
83
129
|
return {
|
|
84
130
|
status: response.status,
|
|
@@ -102,6 +148,7 @@ async function fetchWithClient(useCache, url, requestHeaders, method, useFullUrl
|
|
|
102
148
|
* @param {boolean} options.useGot - Enable custom fetching via Superagent (bypassing browser network stack for intercepted types)
|
|
103
149
|
* @param {boolean} options.useFullUrl - Use full URL for cache keys
|
|
104
150
|
* @param {boolean} options.useCache - Enable caching
|
|
151
|
+
* @param {string|Object|null} options.proxy - Proxy for custom fetch. String: "http://host:port" or "socks5://user:pass@host:port". Object: { type, host, port, user, pass }
|
|
105
152
|
* @param {Object} options.m4w_send_on_post - Custom handler data for Doublelist posts
|
|
106
153
|
* @param {Object} options.m4w_send_on_message - Custom handler data for Doublelist messages
|
|
107
154
|
* @param {Array<string>} options.allowImagePatterns - Array of strings/patterns. If a URL contains any of these, it will NOT be blocked even if blockImage is true.
|
|
@@ -113,9 +160,10 @@ export async function pwRoute({
|
|
|
113
160
|
logger = false,
|
|
114
161
|
blockAds = true,
|
|
115
162
|
blockImage = true,
|
|
116
|
-
useGot =
|
|
163
|
+
useGot = false,
|
|
117
164
|
useFullUrl = true,
|
|
118
165
|
useCache = true,
|
|
166
|
+
proxy = null,
|
|
119
167
|
m4w_send_on_post = null,
|
|
120
168
|
m4w_send_on_message = null,
|
|
121
169
|
allowImagePatterns = [], // Default empty, merged inside
|
|
@@ -149,6 +197,10 @@ export async function pwRoute({
|
|
|
149
197
|
// Define resource types to intercept for custom fetching (useGot)
|
|
150
198
|
const interceptedResourceTypes = ["stylesheet", "script", "font"];
|
|
151
199
|
|
|
200
|
+
// Create proxy agent once (reused for all requests in this route)
|
|
201
|
+
const proxyUrl = formatProxyUrl(proxy);
|
|
202
|
+
const proxyAgent = createProxyAgent(proxyUrl);
|
|
203
|
+
|
|
152
204
|
// If images are NOT blocked, we generally want to intercept/cache them too.
|
|
153
205
|
if (!blockImage) {
|
|
154
206
|
interceptedResourceTypes.push("image");
|
|
@@ -291,7 +343,8 @@ export async function pwRoute({
|
|
|
291
343
|
requestHeaders,
|
|
292
344
|
requestMethod,
|
|
293
345
|
useFullUrl,
|
|
294
|
-
logger
|
|
346
|
+
logger,
|
|
347
|
+
proxyAgent
|
|
295
348
|
);
|
|
296
349
|
|
|
297
350
|
if (response) {
|
|
@@ -29,6 +29,13 @@ export interface PpRouteOptions {
|
|
|
29
29
|
/** Enable caching for requests */
|
|
30
30
|
useCache?: boolean;
|
|
31
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Proxy for custom fetch requests (only used when useGot is true).
|
|
34
|
+
* String: "http://host:port", "socks5://user:pass@host:port"
|
|
35
|
+
* Object: { type, host, port, user, pass }
|
|
36
|
+
*/
|
|
37
|
+
proxy?: string | { type?: string; host: string; port: number; user?: string; pass?: string } | null;
|
|
38
|
+
|
|
32
39
|
/** Data object for Doublelist message interception (POST logic) */
|
|
33
40
|
m4w_send_on_post?: Record<string, any> | null;
|
|
34
41
|
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
import superagent from "superagent";
|
|
3
3
|
import { FiltersEngine, Request } from "@ghostery/adblocker";
|
|
4
4
|
import fetch from "node-fetch";
|
|
5
|
+
import { HttpsProxyAgent } from "https-proxy-agent";
|
|
6
|
+
import { SocksProxyAgent } from "socks-proxy-agent";
|
|
5
7
|
import NodeCache from "node-cache";
|
|
6
8
|
|
|
7
9
|
let AdBlockEngine;
|
|
@@ -37,6 +39,38 @@ export function ppCacheLogs(log_cache = globalCache, interval = 10) {
|
|
|
37
39
|
}
|
|
38
40
|
}
|
|
39
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Normalizes proxy input (string or object) into a URL string.
|
|
44
|
+
* Accepts:
|
|
45
|
+
* - String: "http://host:port", "socks5://user:pass@host:port", etc.
|
|
46
|
+
* - Object: { type, host, port, user, pass }
|
|
47
|
+
* @param {string|Object|null} proxy
|
|
48
|
+
* @returns {string|null} - Proxy URL string or null
|
|
49
|
+
*/
|
|
50
|
+
function formatProxyUrl(proxy) {
|
|
51
|
+
if (!proxy) return null;
|
|
52
|
+
if (typeof proxy === "string") return proxy;
|
|
53
|
+
if (typeof proxy === "object") {
|
|
54
|
+
const { type = "http", host, port, user, pass } = proxy;
|
|
55
|
+
const auth = user && pass ? `${user}:${pass}@` : "";
|
|
56
|
+
return `${type}://${auth}${host}:${port}`;
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Creates an HTTP agent for the given proxy URL.
|
|
63
|
+
* @param {string|null} proxyUrl
|
|
64
|
+
* @returns {Object|null} - HttpsProxyAgent or SocksProxyAgent instance
|
|
65
|
+
*/
|
|
66
|
+
function createProxyAgent(proxyUrl) {
|
|
67
|
+
if (!proxyUrl) return null;
|
|
68
|
+
if (proxyUrl.startsWith("socks")) {
|
|
69
|
+
return new SocksProxyAgent(proxyUrl);
|
|
70
|
+
}
|
|
71
|
+
return new HttpsProxyAgent(proxyUrl);
|
|
72
|
+
}
|
|
73
|
+
|
|
40
74
|
/**
|
|
41
75
|
* Function to fetch resources using Superagent library with optional caching.
|
|
42
76
|
* This mimics the browser's request but handles it in Node.js to allow caching or header manipulation.
|
|
@@ -46,9 +80,10 @@ export function ppCacheLogs(log_cache = globalCache, interval = 10) {
|
|
|
46
80
|
* @param {string} method - HTTP method (GET, POST, etc.)
|
|
47
81
|
* @param {boolean} useFullUrl - Whether to use the full URL as cache key or just origin+path
|
|
48
82
|
* @param {string|false} logger - Log level: "info" (success+error), "error" (errors only), false (no logs)
|
|
83
|
+
* @param {Object|null} proxyAgent - Proxy agent to use for the request
|
|
49
84
|
* @returns {Promise<Object>} - The response object containing status, headers, and body
|
|
50
85
|
*/
|
|
51
|
-
async function fetchWithClient(useCache, url, requestHeaders, method, useFullUrl, logger) {
|
|
86
|
+
async function fetchWithClient(useCache, url, requestHeaders, method, useFullUrl, logger, proxyAgent) {
|
|
52
87
|
// Determine the cache key based on configuration
|
|
53
88
|
let mainUrl = new URL(url).origin + new URL(url).pathname;
|
|
54
89
|
if (useFullUrl) {
|
|
@@ -67,18 +102,29 @@ async function fetchWithClient(useCache, url, requestHeaders, method, useFullUrl
|
|
|
67
102
|
try {
|
|
68
103
|
// Fetch the resource using superagent
|
|
69
104
|
// buffer(true) ensures we get the raw binary data (essential for images/fonts)
|
|
70
|
-
|
|
105
|
+
let request = superagent(method, url).set(requestHeaders).buffer(true);
|
|
106
|
+
|
|
107
|
+
// Apply proxy agent if provided
|
|
108
|
+
if (proxyAgent) {
|
|
109
|
+
request = request.agent(proxyAgent);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const response = await request;
|
|
71
113
|
|
|
72
114
|
// Determine the correct body type (Buffer for binary, text for others)
|
|
73
115
|
const responseBody = response.body instanceof Buffer ? response.body : response.text;
|
|
74
116
|
|
|
75
|
-
// Save to cache
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
117
|
+
// Save to cache only when caching is enabled
|
|
118
|
+
if (useCache) {
|
|
119
|
+
globalCache.set(mainUrl, {
|
|
120
|
+
status: response.status,
|
|
121
|
+
headers: response.headers,
|
|
122
|
+
body: responseBody,
|
|
123
|
+
});
|
|
124
|
+
if (logger === "info") console.log(`Success (cached): ${mainUrl}`);
|
|
125
|
+
} else {
|
|
126
|
+
if (logger === "info") console.log(`Success (not cached): ${mainUrl}`);
|
|
127
|
+
}
|
|
82
128
|
|
|
83
129
|
return {
|
|
84
130
|
status: response.status,
|
|
@@ -92,16 +138,16 @@ async function fetchWithClient(useCache, url, requestHeaders, method, useFullUrl
|
|
|
92
138
|
}
|
|
93
139
|
|
|
94
140
|
/**
|
|
95
|
-
* Main function to set up routing, ad blocking, and request interception in
|
|
141
|
+
* Main function to set up routing, ad blocking, and request interception in Puppeteer.
|
|
96
142
|
* @param {Object} options - Configuration options
|
|
97
|
-
* @param {Object} options.
|
|
98
|
-
* @param {Object} options.page - Playwright page (optional, one is required)
|
|
143
|
+
* @param {Object} options.page - Puppeteer page (required)
|
|
99
144
|
* @param {boolean} options.blockImage - Enable global image blocking
|
|
100
145
|
* @param {boolean} options.blockAds - Enable Ghostery ad blocking
|
|
101
146
|
* @param {string|false} [options.logger="error"] - Log level: "info" (success+error), "error" (errors only), false (no logs)
|
|
102
147
|
* @param {boolean} options.useGot - Enable custom fetching via Superagent (bypassing browser network stack for intercepted types)
|
|
103
148
|
* @param {boolean} options.useFullUrl - Use full URL for cache keys
|
|
104
149
|
* @param {boolean} options.useCache - Enable caching
|
|
150
|
+
* @param {string|Object|null} options.proxy - Proxy for custom fetch. String: "http://host:port" or "socks5://user:pass@host:port". Object: { type, host, port, user, pass }
|
|
105
151
|
* @param {Object} options.m4w_send_on_post - Custom handler data for Doublelist posts
|
|
106
152
|
* @param {Object} options.m4w_send_on_message - Custom handler data for Doublelist messages
|
|
107
153
|
* @param {Array<string>} options.allowImagePatterns - Array of strings/patterns. If a URL contains any of these, it will NOT be blocked even if blockImage is true.
|
|
@@ -112,9 +158,10 @@ export async function ppRoute({
|
|
|
112
158
|
logger = false,
|
|
113
159
|
blockAds = true,
|
|
114
160
|
blockImage = true,
|
|
115
|
-
useGot =
|
|
161
|
+
useGot = false,
|
|
116
162
|
useFullUrl = true,
|
|
117
163
|
useCache = true,
|
|
164
|
+
proxy = null,
|
|
118
165
|
m4w_send_on_post = null,
|
|
119
166
|
m4w_send_on_message = null,
|
|
120
167
|
allowImagePatterns = [], // Default empty, merged inside
|
|
@@ -147,6 +194,10 @@ export async function ppRoute({
|
|
|
147
194
|
// Define resource types to intercept for custom fetching (useGot)
|
|
148
195
|
const interceptedResourceTypes = ["stylesheet", "script", "font"];
|
|
149
196
|
|
|
197
|
+
// Create proxy agent once (reused for all requests in this route)
|
|
198
|
+
const proxyUrl = formatProxyUrl(proxy);
|
|
199
|
+
const proxyAgent = createProxyAgent(proxyUrl);
|
|
200
|
+
|
|
150
201
|
// If images are NOT blocked, we generally want to intercept/cache them too.
|
|
151
202
|
if (!blockImage) {
|
|
152
203
|
interceptedResourceTypes.push("image");
|
|
@@ -295,7 +346,8 @@ export async function ppRoute({
|
|
|
295
346
|
requestHeaders,
|
|
296
347
|
requestMethod,
|
|
297
348
|
useFullUrl,
|
|
298
|
-
logger
|
|
349
|
+
logger,
|
|
350
|
+
proxyAgent
|
|
299
351
|
);
|
|
300
352
|
|
|
301
353
|
if (response) {
|