@fanboynz/network-scanner 1.0.63 → 1.0.64
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/lib/browserhealth.js +104 -14
- package/lib/cdp.js +8 -3
- package/lib/fingerprint.js +1870 -361
- package/nwss.js +286 -69
- package/package.json +1 -1
package/lib/browserhealth.js
CHANGED
|
@@ -11,7 +11,7 @@ const { formatLogMessage, messageColors } = require('./colorize');
|
|
|
11
11
|
* @param {number} timeout - Timeout in milliseconds (default: 5000)
|
|
12
12
|
* @returns {Promise<object>} Health check result
|
|
13
13
|
*/
|
|
14
|
-
async function checkBrowserHealth(browserInstance, timeout =
|
|
14
|
+
async function checkBrowserHealth(browserInstance, timeout = 8000) {
|
|
15
15
|
const healthResult = {
|
|
16
16
|
healthy: false,
|
|
17
17
|
pageCount: 0,
|
|
@@ -44,7 +44,7 @@ async function checkBrowserHealth(browserInstance, timeout = 5000) {
|
|
|
44
44
|
healthResult.responseTime = Date.now() - startTime;
|
|
45
45
|
|
|
46
46
|
// Test 3: Check for excessive pages (memory leak indicator)
|
|
47
|
-
if (pages.length >
|
|
47
|
+
if (pages.length > 30) {
|
|
48
48
|
healthResult.recommendations.push('Too many open pages - consider browser restart');
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -83,7 +83,7 @@ async function checkBrowserHealth(browserInstance, timeout = 5000) {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
// Test 5: Check response time performance
|
|
86
|
-
if (healthResult.responseTime >
|
|
86
|
+
if (healthResult.responseTime > 5000) {
|
|
87
87
|
healthResult.recommendations.push('Slow browser response - consider restart');
|
|
88
88
|
}
|
|
89
89
|
|
|
@@ -95,11 +95,19 @@ async function checkBrowserHealth(browserInstance, timeout = 5000) {
|
|
|
95
95
|
healthResult.responseTime = Date.now() - startTime;
|
|
96
96
|
|
|
97
97
|
// Categorize error types for better recommendations
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
error.message.includes('Target closed')) {
|
|
98
|
+
// Enhanced error categorization for Puppeteer 23.x
|
|
99
|
+
if (isCriticalProtocolError(error)) {
|
|
101
100
|
healthResult.recommendations.push('Browser restart required - critical protocol error');
|
|
102
101
|
healthResult.criticalError = true;
|
|
102
|
+
} else if (error.message.includes('WebSocket') ||
|
|
103
|
+
error.message.includes('Connection terminated') ||
|
|
104
|
+
error.message.includes('Network service crashed')) {
|
|
105
|
+
// New error types more common in Puppeteer 23.x
|
|
106
|
+
healthResult.recommendations.push('Browser restart required - connection error');
|
|
107
|
+
healthResult.criticalError = true;
|
|
108
|
+
} else if (error.message.includes('AbortError') ||
|
|
109
|
+
error.message.includes('Operation was aborted')) {
|
|
110
|
+
healthResult.recommendations.push('Browser restart recommended - operation aborted');
|
|
103
111
|
} else if (error.message.includes('timeout') || error.message.includes('unresponsive')) {
|
|
104
112
|
healthResult.recommendations.push('Browser restart required - unresponsive');
|
|
105
113
|
healthResult.criticalError = true;
|
|
@@ -176,7 +184,18 @@ function isCriticalProtocolError(error) {
|
|
|
176
184
|
'Session closed',
|
|
177
185
|
'Connection closed',
|
|
178
186
|
'Browser has been closed',
|
|
179
|
-
'Runtime.evaluate timed out'
|
|
187
|
+
'Runtime.evaluate timed out',
|
|
188
|
+
// New Puppeteer 23.x critical errors
|
|
189
|
+
'WebSocket is not open',
|
|
190
|
+
'WebSocket connection lost',
|
|
191
|
+
'Connection terminated',
|
|
192
|
+
'Network service crashed',
|
|
193
|
+
'Browser disconnected',
|
|
194
|
+
'CDP session invalid',
|
|
195
|
+
'Browser process exited',
|
|
196
|
+
'Navigation timeout of',
|
|
197
|
+
'Page crashed',
|
|
198
|
+
'Renderer process crashed'
|
|
180
199
|
];
|
|
181
200
|
|
|
182
201
|
return criticalErrors.some(criticalError =>
|
|
@@ -184,6 +203,54 @@ function isCriticalProtocolError(error) {
|
|
|
184
203
|
);
|
|
185
204
|
}
|
|
186
205
|
|
|
206
|
+
/**
|
|
207
|
+
* Enhanced browser connectivity test for Puppeteer 23.x
|
|
208
|
+
* Tests WebSocket connection and CDP session validity
|
|
209
|
+
*/
|
|
210
|
+
async function testBrowserConnectivity(browserInstance, timeout = 2500) {
|
|
211
|
+
const connectivityResult = {
|
|
212
|
+
connected: false,
|
|
213
|
+
cdpResponsive: false,
|
|
214
|
+
websocketHealthy: false,
|
|
215
|
+
error: null
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
try {
|
|
219
|
+
// Test 1: Basic browser connection
|
|
220
|
+
const isConnected = browserInstance.isConnected();
|
|
221
|
+
connectivityResult.connected = isConnected;
|
|
222
|
+
|
|
223
|
+
if (!isConnected) {
|
|
224
|
+
connectivityResult.error = 'Browser is not connected';
|
|
225
|
+
return connectivityResult;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Test 2: CDP responsiveness with version check
|
|
229
|
+
try {
|
|
230
|
+
const version = await Promise.race([
|
|
231
|
+
browserInstance.version(),
|
|
232
|
+
new Promise((_, reject) =>
|
|
233
|
+
setTimeout(() => reject(new Error('CDP version check timeout')), timeout)
|
|
234
|
+
)
|
|
235
|
+
]);
|
|
236
|
+
|
|
237
|
+
connectivityResult.cdpResponsive = true;
|
|
238
|
+
connectivityResult.websocketHealthy = true; // If version works, WebSocket is healthy
|
|
239
|
+
|
|
240
|
+
} catch (cdpError) {
|
|
241
|
+
connectivityResult.error = `CDP not responsive: ${cdpError.message}`;
|
|
242
|
+
if (cdpError.message.includes('WebSocket')) {
|
|
243
|
+
connectivityResult.websocketHealthy = false;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
} catch (error) {
|
|
248
|
+
connectivityResult.error = error.message;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return connectivityResult;
|
|
252
|
+
}
|
|
253
|
+
|
|
187
254
|
/**
|
|
188
255
|
* Performs comprehensive browser health assessment
|
|
189
256
|
* @param {import('puppeteer').Browser} browserInstance - Puppeteer browser instance
|
|
@@ -192,8 +259,9 @@ function isCriticalProtocolError(error) {
|
|
|
192
259
|
*/
|
|
193
260
|
async function performHealthAssessment(browserInstance, options = {}) {
|
|
194
261
|
const {
|
|
195
|
-
timeout =
|
|
262
|
+
timeout = 8000,
|
|
196
263
|
checkMemory = true,
|
|
264
|
+
testConnectivity = true,
|
|
197
265
|
forceDebug = false
|
|
198
266
|
} = options;
|
|
199
267
|
|
|
@@ -202,6 +270,7 @@ async function performHealthAssessment(browserInstance, options = {}) {
|
|
|
202
270
|
timestamp: new Date().toISOString(),
|
|
203
271
|
browser: {},
|
|
204
272
|
memory: {},
|
|
273
|
+
connectivity: {},
|
|
205
274
|
recommendations: [],
|
|
206
275
|
needsRestart: false
|
|
207
276
|
};
|
|
@@ -213,6 +282,11 @@ async function performHealthAssessment(browserInstance, options = {}) {
|
|
|
213
282
|
// Browser responsiveness check
|
|
214
283
|
assessment.browser = await checkBrowserHealth(browserInstance, timeout);
|
|
215
284
|
|
|
285
|
+
// Enhanced connectivity check for Puppeteer 23.x
|
|
286
|
+
if (testConnectivity) {
|
|
287
|
+
assessment.connectivity = await testBrowserConnectivity(browserInstance, timeout);
|
|
288
|
+
}
|
|
289
|
+
|
|
216
290
|
// Memory usage check (if enabled and available)
|
|
217
291
|
if (checkMemory) {
|
|
218
292
|
assessment.memory = await checkBrowserMemory(browserInstance);
|
|
@@ -221,6 +295,7 @@ async function performHealthAssessment(browserInstance, options = {}) {
|
|
|
221
295
|
// Combine recommendations
|
|
222
296
|
assessment.recommendations = [
|
|
223
297
|
...assessment.browser.recommendations,
|
|
298
|
+
...(assessment.connectivity.error ? [`Connectivity issue: ${assessment.connectivity.error}`] : []),
|
|
224
299
|
...(assessment.memory.recommendations || [])
|
|
225
300
|
];
|
|
226
301
|
|
|
@@ -231,6 +306,9 @@ async function performHealthAssessment(browserInstance, options = {}) {
|
|
|
231
306
|
} else if (assessment.browser.criticalError) {
|
|
232
307
|
assessment.overall = 'critical';
|
|
233
308
|
assessment.needsRestart = true;
|
|
309
|
+
} else if (testConnectivity && (!assessment.connectivity.connected || !assessment.connectivity.cdpResponsive)) {
|
|
310
|
+
assessment.overall = 'disconnected';
|
|
311
|
+
assessment.needsRestart = true;
|
|
234
312
|
} else if (assessment.recommendations.length > 0) {
|
|
235
313
|
assessment.overall = 'degraded';
|
|
236
314
|
assessment.needsRestart = assessment.recommendations.some(rec =>
|
|
@@ -279,8 +357,9 @@ async function monitorBrowserHealth(browserInstance, context = {}, options = {})
|
|
|
279
357
|
try {
|
|
280
358
|
// Perform health assessment
|
|
281
359
|
const assessment = await performHealthAssessment(browserInstance, {
|
|
282
|
-
timeout:
|
|
360
|
+
timeout: 8000,
|
|
283
361
|
checkMemory: true,
|
|
362
|
+
testConnectivity: true, // Enable enhanced connectivity testing
|
|
284
363
|
forceDebug
|
|
285
364
|
});
|
|
286
365
|
|
|
@@ -290,15 +369,22 @@ async function monitorBrowserHealth(browserInstance, context = {}, options = {})
|
|
|
290
369
|
if (assessment.browser.criticalError) {
|
|
291
370
|
result.shouldRestart = true;
|
|
292
371
|
result.reason = `Critical protocol error detected - immediate restart required`;
|
|
372
|
+
} else if (assessment.connectivity && (!assessment.connectivity.connected || !assessment.connectivity.cdpResponsive)) {
|
|
373
|
+
result.shouldRestart = true;
|
|
374
|
+
result.reason = `Browser connectivity lost - WebSocket/CDP failure`;
|
|
293
375
|
} else if (assessment.needsRestart) {
|
|
294
376
|
result.shouldRestart = true;
|
|
295
377
|
result.reason = `Browser health: ${assessment.overall} - ${assessment.recommendations[0] || 'restart needed'}`;
|
|
296
378
|
} else if (urlsSinceCleanup >= cleanupInterval) {
|
|
297
379
|
result.shouldRestart = true;
|
|
298
380
|
result.reason = `Scheduled cleanup after ${urlsSinceCleanup} URLs`;
|
|
299
|
-
} else if (assessment.browser.responseTime >
|
|
381
|
+
} else if (assessment.browser.responseTime > 6000) {
|
|
382
|
+
result.shouldRestart = true;
|
|
383
|
+
result.reason = `Slow browser response: ${assessment.browser.responseTime}ms (threshold: 6000ms)`;
|
|
384
|
+
} else if (assessment.browser.pageCount > 40) {
|
|
385
|
+
// More aggressive page count monitoring for Puppeteer 23.x
|
|
300
386
|
result.shouldRestart = true;
|
|
301
|
-
result.reason = `
|
|
387
|
+
result.reason = `Too many open pages: ${assessment.browser.pageCount} (memory leak protection)`;
|
|
302
388
|
}
|
|
303
389
|
|
|
304
390
|
// Logging
|
|
@@ -308,7 +394,9 @@ async function monitorBrowserHealth(browserInstance, context = {}, options = {})
|
|
|
308
394
|
}
|
|
309
395
|
|
|
310
396
|
if (forceDebug && !result.shouldRestart) {
|
|
311
|
-
|
|
397
|
+
const connectivity = assessment.connectivity.connected ? 'connected' : 'disconnected';
|
|
398
|
+
const cdp = assessment.connectivity.cdpResponsive ? 'responsive' : 'unresponsive';
|
|
399
|
+
console.log(formatLogMessage('debug', `Browser health OK - continuing (pages: ${assessment.browser.pageCount}, response: ${assessment.browser.responseTime}ms, ${connectivity}, CDP: ${cdp})`));
|
|
312
400
|
}
|
|
313
401
|
|
|
314
402
|
} catch (monitorError) {
|
|
@@ -330,8 +418,9 @@ async function monitorBrowserHealth(browserInstance, context = {}, options = {})
|
|
|
330
418
|
*/
|
|
331
419
|
async function isBrowserHealthy(browserInstance) {
|
|
332
420
|
try {
|
|
333
|
-
const health = await checkBrowserHealth(browserInstance,
|
|
334
|
-
|
|
421
|
+
const health = await checkBrowserHealth(browserInstance, 5000); // Faster timeout
|
|
422
|
+
const connectivity = await testBrowserConnectivity(browserInstance, 3000);
|
|
423
|
+
return health.healthy && connectivity.connected && connectivity.cdpResponsive;
|
|
335
424
|
} catch (error) {
|
|
336
425
|
return false;
|
|
337
426
|
}
|
|
@@ -340,6 +429,7 @@ async function isBrowserHealthy(browserInstance) {
|
|
|
340
429
|
module.exports = {
|
|
341
430
|
checkBrowserHealth,
|
|
342
431
|
checkBrowserMemory,
|
|
432
|
+
testBrowserConnectivity,
|
|
343
433
|
performHealthAssessment,
|
|
344
434
|
monitorBrowserHealth,
|
|
345
435
|
isBrowserHealthy,
|
package/lib/cdp.js
CHANGED
|
@@ -87,8 +87,9 @@ async function createCDPSession(page, currentUrl, options = {}) {
|
|
|
87
87
|
let cdpSession = null;
|
|
88
88
|
|
|
89
89
|
try {
|
|
90
|
-
// Create CDP session
|
|
91
|
-
|
|
90
|
+
// Create CDP session using modern Puppeteer 20+ API
|
|
91
|
+
// page.target().createCDPSession() was deprecated in 19+ and removed in 20+
|
|
92
|
+
cdpSession = await page.createCDPSession();
|
|
92
93
|
|
|
93
94
|
// Enable network domain - required for network event monitoring
|
|
94
95
|
await cdpSession.send('Network.enable');
|
|
@@ -140,8 +141,12 @@ async function createCDPSession(page, currentUrl, options = {}) {
|
|
|
140
141
|
cdpSession = null; // Reset on failure
|
|
141
142
|
|
|
142
143
|
// Categorize CDP errors for proper handling
|
|
144
|
+
// Enhanced error handling for Puppeteer 20+ error patterns
|
|
143
145
|
if (cdpErr.message.includes('Network.enable timed out') ||
|
|
144
|
-
cdpErr.message.includes('Protocol error')
|
|
146
|
+
cdpErr.message.includes('Protocol error') ||
|
|
147
|
+
cdpErr.message.includes('Session closed') ||
|
|
148
|
+
cdpErr.message.includes('Target closed') ||
|
|
149
|
+
cdpErr.message.includes('Browser has been closed')) {
|
|
145
150
|
// CRITICAL ERROR: Browser is broken and needs restart
|
|
146
151
|
// Re-throw these errors so calling code can handle browser restart
|
|
147
152
|
throw new Error(`Browser protocol broken: ${cdpErr.message}`);
|