@fanboynz/network-scanner 1.0.35
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/.github/workflows/npm-publish.yml +33 -0
- package/JSONMANUAL.md +121 -0
- package/LICENSE +674 -0
- package/README.md +357 -0
- package/config.json +74 -0
- package/lib/browserexit.js +522 -0
- package/lib/browserhealth.js +308 -0
- package/lib/cloudflare.js +660 -0
- package/lib/colorize.js +168 -0
- package/lib/compare.js +159 -0
- package/lib/compress.js +129 -0
- package/lib/fingerprint.js +613 -0
- package/lib/flowproxy.js +274 -0
- package/lib/grep.js +348 -0
- package/lib/ignore_similar.js +237 -0
- package/lib/nettools.js +1200 -0
- package/lib/output.js +633 -0
- package/lib/redirect.js +384 -0
- package/lib/searchstring.js +561 -0
- package/lib/validate_rules.js +1107 -0
- package/nwss.1 +824 -0
- package/nwss.js +2488 -0
- package/package.json +45 -0
- package/regex-samples.md +27 -0
- package/scanner-script-org.js +588 -0
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser health monitoring module for nwss.js
|
|
3
|
+
* Provides health checks and recovery mechanisms to prevent protocol timeouts
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { formatLogMessage, messageColors } = require('./colorize');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Checks if browser instance is still responsive
|
|
10
|
+
* @param {import('puppeteer').Browser} browserInstance - Puppeteer browser instance
|
|
11
|
+
* @param {number} timeout - Timeout in milliseconds (default: 5000)
|
|
12
|
+
* @returns {Promise<object>} Health check result
|
|
13
|
+
*/
|
|
14
|
+
async function checkBrowserHealth(browserInstance, timeout = 5000) {
|
|
15
|
+
const healthResult = {
|
|
16
|
+
healthy: false,
|
|
17
|
+
pageCount: 0,
|
|
18
|
+
error: null,
|
|
19
|
+
responseTime: 0,
|
|
20
|
+
recommendations: []
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const startTime = Date.now();
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
// Test 1: Check if browser is connected
|
|
27
|
+
if (!browserInstance || browserInstance.process() === null) {
|
|
28
|
+
healthResult.error = 'Browser process not running';
|
|
29
|
+
healthResult.recommendations.push('Create new browser instance');
|
|
30
|
+
return healthResult;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Test 2: Try to get pages list with timeout
|
|
34
|
+
const pages = await Promise.race([
|
|
35
|
+
browserInstance.pages(),
|
|
36
|
+
new Promise((_, reject) =>
|
|
37
|
+
setTimeout(() => reject(new Error('Browser unresponsive - pages() timeout')), timeout)
|
|
38
|
+
)
|
|
39
|
+
]);
|
|
40
|
+
|
|
41
|
+
healthResult.pageCount = pages.length;
|
|
42
|
+
healthResult.responseTime = Date.now() - startTime;
|
|
43
|
+
|
|
44
|
+
// Test 3: Check for excessive pages (memory leak indicator)
|
|
45
|
+
if (pages.length > 20) {
|
|
46
|
+
healthResult.recommendations.push('Too many open pages - consider browser restart');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Test 4: Try to create a test page to verify browser functionality
|
|
50
|
+
let testPage = null;
|
|
51
|
+
try {
|
|
52
|
+
testPage = await Promise.race([
|
|
53
|
+
browserInstance.newPage(),
|
|
54
|
+
new Promise((_, reject) =>
|
|
55
|
+
setTimeout(() => reject(new Error('Page creation timeout')), timeout)
|
|
56
|
+
)
|
|
57
|
+
]);
|
|
58
|
+
|
|
59
|
+
// Quick test navigation to about:blank
|
|
60
|
+
await Promise.race([
|
|
61
|
+
testPage.goto('about:blank'),
|
|
62
|
+
new Promise((_, reject) =>
|
|
63
|
+
setTimeout(() => reject(new Error('Navigation timeout')), timeout)
|
|
64
|
+
)
|
|
65
|
+
]);
|
|
66
|
+
|
|
67
|
+
await testPage.close();
|
|
68
|
+
|
|
69
|
+
} catch (pageTestError) {
|
|
70
|
+
if (testPage && !testPage.isClosed()) {
|
|
71
|
+
try { await testPage.close(); } catch (e) { /* ignore */ }
|
|
72
|
+
}
|
|
73
|
+
healthResult.error = `Page creation/navigation failed: ${pageTestError.message}`;
|
|
74
|
+
healthResult.recommendations.push('Browser restart recommended');
|
|
75
|
+
return healthResult;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Test 5: Check response time performance
|
|
79
|
+
if (healthResult.responseTime > 3000) {
|
|
80
|
+
healthResult.recommendations.push('Slow browser response - consider restart');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// If all tests pass
|
|
84
|
+
healthResult.healthy = true;
|
|
85
|
+
|
|
86
|
+
} catch (error) {
|
|
87
|
+
healthResult.error = error.message;
|
|
88
|
+
healthResult.responseTime = Date.now() - startTime;
|
|
89
|
+
|
|
90
|
+
// Categorize error types for better recommendations
|
|
91
|
+
if (error.message.includes('timeout') || error.message.includes('unresponsive')) {
|
|
92
|
+
healthResult.recommendations.push('Browser restart required - unresponsive');
|
|
93
|
+
} else if (error.message.includes('Protocol error') || error.message.includes('Target closed')) {
|
|
94
|
+
healthResult.recommendations.push('Browser restart required - protocol error');
|
|
95
|
+
} else {
|
|
96
|
+
healthResult.recommendations.push('Browser restart recommended - unknown error');
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return healthResult;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Checks memory usage of browser process (if available)
|
|
105
|
+
* @param {import('puppeteer').Browser} browserInstance - Puppeteer browser instance
|
|
106
|
+
* @returns {Promise<object>} Memory usage information
|
|
107
|
+
*/
|
|
108
|
+
async function checkBrowserMemory(browserInstance) {
|
|
109
|
+
const memoryResult = {
|
|
110
|
+
available: false,
|
|
111
|
+
usage: null,
|
|
112
|
+
error: null,
|
|
113
|
+
recommendations: []
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
const browserProcess = browserInstance.process();
|
|
118
|
+
if (!browserProcess || !browserProcess.pid) {
|
|
119
|
+
memoryResult.error = 'No browser process available';
|
|
120
|
+
return memoryResult;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Try to get process memory info (Linux/Unix)
|
|
124
|
+
try {
|
|
125
|
+
const { execSync } = require('child_process');
|
|
126
|
+
const memInfo = execSync(`ps -p ${browserProcess.pid} -o rss=`, { encoding: 'utf8', timeout: 2000 });
|
|
127
|
+
const memoryKB = parseInt(memInfo.trim());
|
|
128
|
+
|
|
129
|
+
if (!isNaN(memoryKB)) {
|
|
130
|
+
const memoryMB = Math.round(memoryKB / 1024);
|
|
131
|
+
memoryResult.available = true;
|
|
132
|
+
memoryResult.usage = {
|
|
133
|
+
rss: memoryKB,
|
|
134
|
+
rssMB: memoryMB
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
// Memory usage recommendations
|
|
138
|
+
if (memoryMB > 1000) {
|
|
139
|
+
memoryResult.recommendations.push(`High memory usage: ${memoryMB}MB - restart recommended`);
|
|
140
|
+
} else if (memoryMB > 500) {
|
|
141
|
+
memoryResult.recommendations.push(`Elevated memory usage: ${memoryMB}MB - monitor closely`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
} catch (psError) {
|
|
145
|
+
memoryResult.error = `Memory check failed: ${psError.message}`;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
} catch (error) {
|
|
149
|
+
memoryResult.error = error.message;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return memoryResult;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Performs comprehensive browser health assessment
|
|
157
|
+
* @param {import('puppeteer').Browser} browserInstance - Puppeteer browser instance
|
|
158
|
+
* @param {object} options - Health check options
|
|
159
|
+
* @returns {Promise<object>} Comprehensive health report
|
|
160
|
+
*/
|
|
161
|
+
async function performHealthAssessment(browserInstance, options = {}) {
|
|
162
|
+
const {
|
|
163
|
+
timeout = 5000,
|
|
164
|
+
checkMemory = true,
|
|
165
|
+
forceDebug = false
|
|
166
|
+
} = options;
|
|
167
|
+
|
|
168
|
+
const assessment = {
|
|
169
|
+
overall: 'unknown',
|
|
170
|
+
timestamp: new Date().toISOString(),
|
|
171
|
+
browser: {},
|
|
172
|
+
memory: {},
|
|
173
|
+
recommendations: [],
|
|
174
|
+
needsRestart: false
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
if (forceDebug) {
|
|
178
|
+
console.log(formatLogMessage('debug', 'Starting browser health assessment...'));
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Browser responsiveness check
|
|
182
|
+
assessment.browser = await checkBrowserHealth(browserInstance, timeout);
|
|
183
|
+
|
|
184
|
+
// Memory usage check (if enabled and available)
|
|
185
|
+
if (checkMemory) {
|
|
186
|
+
assessment.memory = await checkBrowserMemory(browserInstance);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Combine recommendations
|
|
190
|
+
assessment.recommendations = [
|
|
191
|
+
...assessment.browser.recommendations,
|
|
192
|
+
...(assessment.memory.recommendations || [])
|
|
193
|
+
];
|
|
194
|
+
|
|
195
|
+
// Determine overall health and restart necessity
|
|
196
|
+
if (!assessment.browser.healthy) {
|
|
197
|
+
assessment.overall = 'unhealthy';
|
|
198
|
+
assessment.needsRestart = true;
|
|
199
|
+
} else if (assessment.recommendations.length > 0) {
|
|
200
|
+
assessment.overall = 'degraded';
|
|
201
|
+
assessment.needsRestart = assessment.recommendations.some(rec =>
|
|
202
|
+
rec.includes('restart required') ||
|
|
203
|
+
rec.includes('High memory usage')
|
|
204
|
+
);
|
|
205
|
+
} else {
|
|
206
|
+
assessment.overall = 'healthy';
|
|
207
|
+
assessment.needsRestart = false;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (forceDebug) {
|
|
211
|
+
console.log(formatLogMessage('debug', `Health assessment complete: ${assessment.overall}`));
|
|
212
|
+
if (assessment.recommendations.length > 0) {
|
|
213
|
+
console.log(formatLogMessage('debug', `Recommendations: ${assessment.recommendations.join(', ')}`));
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return assessment;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Monitors browser health and suggests actions for nwss.js integration
|
|
222
|
+
* @param {import('puppeteer').Browser} browserInstance - Puppeteer browser instance
|
|
223
|
+
* @param {object} context - Context information for logging
|
|
224
|
+
* @param {object} options - Monitoring options
|
|
225
|
+
* @returns {Promise<object>} Monitoring result with action suggestions
|
|
226
|
+
*/
|
|
227
|
+
async function monitorBrowserHealth(browserInstance, context = {}, options = {}) {
|
|
228
|
+
const {
|
|
229
|
+
siteIndex = 0,
|
|
230
|
+
totalSites = 0,
|
|
231
|
+
urlsSinceCleanup = 0,
|
|
232
|
+
cleanupInterval = 40,
|
|
233
|
+
forceDebug = false,
|
|
234
|
+
silentMode = false
|
|
235
|
+
} = options;
|
|
236
|
+
|
|
237
|
+
const result = {
|
|
238
|
+
shouldRestart: false,
|
|
239
|
+
shouldContinue: true,
|
|
240
|
+
reason: null,
|
|
241
|
+
assessment: null
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
try {
|
|
245
|
+
// Perform health assessment
|
|
246
|
+
const assessment = await performHealthAssessment(browserInstance, {
|
|
247
|
+
timeout: 5000,
|
|
248
|
+
checkMemory: true,
|
|
249
|
+
forceDebug
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
result.assessment = assessment;
|
|
253
|
+
|
|
254
|
+
// Decision logic for restart
|
|
255
|
+
if (assessment.needsRestart) {
|
|
256
|
+
result.shouldRestart = true;
|
|
257
|
+
result.reason = `Browser health: ${assessment.overall} - ${assessment.recommendations[0] || 'restart needed'}`;
|
|
258
|
+
} else if (urlsSinceCleanup >= cleanupInterval) {
|
|
259
|
+
result.shouldRestart = true;
|
|
260
|
+
result.reason = `Scheduled cleanup after ${urlsSinceCleanup} URLs`;
|
|
261
|
+
} else if (assessment.browser.responseTime > 4000) {
|
|
262
|
+
result.shouldRestart = true;
|
|
263
|
+
result.reason = `Slow browser response: ${assessment.browser.responseTime}ms`;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Logging
|
|
267
|
+
if (!silentMode && result.shouldRestart) {
|
|
268
|
+
const progress = totalSites > 0 ? ` (${siteIndex + 1}/${totalSites})` : '';
|
|
269
|
+
console.log(`\n${messageColors.fileOp('?? Browser restart needed')} before site${progress}: ${result.reason}`);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (forceDebug && !result.shouldRestart) {
|
|
273
|
+
console.log(formatLogMessage('debug', `Browser health OK - continuing (pages: ${assessment.browser.pageCount}, response: ${assessment.browser.responseTime}ms)`));
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
} catch (monitorError) {
|
|
277
|
+
result.shouldRestart = true;
|
|
278
|
+
result.reason = `Health monitoring failed: ${monitorError.message}`;
|
|
279
|
+
|
|
280
|
+
if (forceDebug) {
|
|
281
|
+
console.log(formatLogMessage('debug', `Browser health monitoring error: ${monitorError.message}`));
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return result;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Simple health check function for quick integration
|
|
290
|
+
* @param {import('puppeteer').Browser} browserInstance - Puppeteer browser instance
|
|
291
|
+
* @returns {Promise<boolean>} True if browser is healthy, false otherwise
|
|
292
|
+
*/
|
|
293
|
+
async function isBrowserHealthy(browserInstance) {
|
|
294
|
+
try {
|
|
295
|
+
const health = await checkBrowserHealth(browserInstance, 3000);
|
|
296
|
+
return health.healthy;
|
|
297
|
+
} catch (error) {
|
|
298
|
+
return false;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
module.exports = {
|
|
303
|
+
checkBrowserHealth,
|
|
304
|
+
checkBrowserMemory,
|
|
305
|
+
performHealthAssessment,
|
|
306
|
+
monitorBrowserHealth,
|
|
307
|
+
isBrowserHealthy
|
|
308
|
+
};
|