From 1662c1efba93b8f8c2513f109b39ae9ec84415ce Mon Sep 17 00:00:00 2001 From: zhom <2717306+zhom@users.noreply.github.com> Date: Thu, 7 Aug 2025 00:45:04 +0400 Subject: [PATCH] refactor: display storage errors for nodecar in json --- nodecar/package.json | 1 - nodecar/src/camoufox-launcher.ts | 113 +------------------------------ nodecar/src/camoufox-storage.ts | 28 +++++--- nodecar/src/proxy-worker.ts | 21 ++---- 4 files changed, 28 insertions(+), 135 deletions(-) diff --git a/nodecar/package.json b/nodecar/package.json index 50ab9e3..a1ff75b 100644 --- a/nodecar/package.json +++ b/nodecar/package.json @@ -8,7 +8,6 @@ "watch": "nodemon --exec ts-node --esm ./src/index.ts --watch src", "dev": "node --loader ts-node/esm ./src/index.ts", "start": "tsc && node ./dist/index.js", - "test": "tsc && node ./dist/test-proxy.js", "rename-binary": "sh ./copy-binary.sh", "build": "tsc && banderole bundle . --output nodecar-bin && pnpm rename-binary", "build:mac-aarch64": "tsc && banderole bundle . --output nodecar-bin && pnpm rename-binary", diff --git a/nodecar/src/camoufox-launcher.ts b/nodecar/src/camoufox-launcher.ts index 72dc555..3618140 100644 --- a/nodecar/src/camoufox-launcher.ts +++ b/nodecar/src/camoufox-launcher.ts @@ -11,98 +11,6 @@ import { saveCamoufoxConfig, } from "./camoufox-storage.js"; -/** - * Convert fingerprint-generator format to camoufox fingerprint format (reverse of convertCamoufoxToFingerprintGenerator) - * @param fingerprintObj The fingerprint-generator object - * @returns camoufox fingerprint object - */ -export function convertFingerprintGeneratorToCamoufox( - fingerprintObj: Record, -): Record { - const camoufoxData: Record = {}; - - // Reverse mappings from fingerprint-generator structure to camoufox keys - const reverseMappings: Record = { - // Navigator properties - "navigator.userAgent": "navigator.userAgent", - "navigator.platform": "navigator.platform", - "navigator.hardwareConcurrency": "navigator.hardwareConcurrency", - "navigator.maxTouchPoints": "navigator.maxTouchPoints", - "navigator.doNotTrack": "navigator.doNotTrack", - "navigator.appCodeName": "navigator.appCodeName", - "navigator.appName": "navigator.appName", - "navigator.appVersion": "navigator.appVersion", - "navigator.oscpu": "navigator.oscpu", - "navigator.product": "navigator.product", - "navigator.language": "navigator.language", - "navigator.languages": "navigator.languages", - "navigator.globalPrivacyControl": "navigator.globalPrivacyControl", - - // Screen properties - "screen.width": "screen.width", - "screen.height": "screen.height", - "screen.availWidth": "screen.availWidth", - "screen.availHeight": "screen.availHeight", - "screen.availTop": "screen.availTop", - "screen.availLeft": "screen.availLeft", - "screen.colorDepth": "screen.colorDepth", - "screen.pixelDepth": "screen.pixelDepth", - "screen.outerWidth": "window.outerWidth", - "screen.outerHeight": "window.outerHeight", - "screen.innerWidth": "window.innerWidth", - "screen.innerHeight": "window.innerHeight", - "screen.screenX": "window.screenX", - "screen.screenY": "window.screenY", - "screen.pageXOffset": "screen.pageXOffset", - "screen.pageYOffset": "screen.pageYOffset", - "screen.devicePixelRatio": "window.devicePixelRatio", - "screen.clientWidth": "document.body.clientWidth", - "screen.clientHeight": "document.body.clientHeight", - - // WebGL properties - "videoCard.vendor": "webGl:vendor", - "videoCard.renderer": "webGl:renderer", - - // Headers - "headers.Accept-Encoding": "headers.Accept-Encoding", - - // Battery - "battery.charging": "battery:charging", - "battery.chargingTime": "battery:chargingTime", - "battery.dischargingTime": "battery:dischargingTime", - }; - - // Apply reverse mappings - for (const [fingerprintPath, camoufoxKey] of Object.entries( - reverseMappings, - )) { - const pathParts = fingerprintPath.split("."); - let current = fingerprintObj; - - // Navigate to the nested property - for (let i = 0; i < pathParts.length - 1; i++) { - const part = pathParts[i]; - if (!current[part]) { - break; - } - current = current[part]; - } - - // Get the final value - const finalKey = pathParts[pathParts.length - 1]; - if (current && current[finalKey] !== undefined) { - camoufoxData[camoufoxKey] = current[finalKey]; - } - } - - // Handle fonts separately - if (fingerprintObj.fonts && Array.isArray(fingerprintObj.fonts)) { - camoufoxData.fonts = fingerprintObj.fonts; - } - - return camoufoxData; -} - /** * Convert camoufox fingerprint format to fingerprint-generator format * @param camoufoxFingerprint The camoufox fingerprint object @@ -367,37 +275,20 @@ export async function stopCamoufoxProcess(id: string): Promise { } try { - console.log(`Stopping Camoufox process ${id} (PID: ${config.processId})`); - // Method 1: If we have a process ID, kill by PID with proper signal sequence if (config.processId) { try { // First try SIGTERM for graceful shutdown process.kill(config.processId, "SIGTERM"); - console.log(`Sent SIGTERM to Camoufox process ${config.processId}`); - // Give it more time to terminate gracefully (increased from 2s to 5s) await new Promise((resolve) => setTimeout(resolve, 5000)); // Check if process is still running try { process.kill(config.processId, 0); // Signal 0 checks if process exists - // Process still exists, force kill - console.log( - `Camoufox process ${config.processId} still running, sending SIGKILL`, - ); process.kill(config.processId, "SIGKILL"); - } catch { - // Process already terminated - console.log( - `Camoufox process ${config.processId} terminated gracefully`, - ); - } - } catch { - console.log( - `Camoufox process ${config.processId} not found or already terminated`, - ); - } + } catch {} + } catch {} } // Method 2: Pattern-based kill as fallback diff --git a/nodecar/src/camoufox-storage.ts b/nodecar/src/camoufox-storage.ts index cb06f4f..1bb86e7 100644 --- a/nodecar/src/camoufox-storage.ts +++ b/nodecar/src/camoufox-storage.ts @@ -43,7 +43,10 @@ export function getCamoufoxConfig(id: string): CamoufoxConfig | null { const content = fs.readFileSync(filePath, "utf-8"); return JSON.parse(content) as CamoufoxConfig; } catch (error) { - console.error(`Error reading Camoufox config ${id}:`, error); + console.error({ + message: `Error reading Camoufox config ${id}`, + error: (error as Error).message, + }); return null; } } @@ -64,7 +67,10 @@ export function deleteCamoufoxConfig(id: string): boolean { fs.unlinkSync(filePath); return true; } catch (error) { - console.error(`Error deleting Camoufox config ${id}:`, error); + console.error({ + message: `Error deleting Camoufox config ${id}`, + error: (error as Error).message, + }); return false; } } @@ -90,13 +96,16 @@ export function listCamoufoxConfigs(): CamoufoxConfig[] { ); return JSON.parse(content) as CamoufoxConfig; } catch (error) { - console.error(`Error reading Camoufox config ${file}:`, error); + console.error({ + message: `Error reading Camoufox config ${file}`, + error, + }); return null; } }) .filter((config): config is CamoufoxConfig => config !== null); } catch (error) { - console.error("Error listing Camoufox configs:", error); + console.error({ message: "Error listing Camoufox configs:", error }); return []; } } @@ -115,13 +124,16 @@ export function updateCamoufoxConfig(config: CamoufoxConfig): boolean { return true; } catch (error) { if ((error as NodeJS.ErrnoException).code === "ENOENT") { - console.error( - `Config ${config.id} was deleted while the app was running`, - ); + console.error({ + message: `Config ${config.id} was deleted while the app was running`, + }); return false; } - console.error(`Error updating Camoufox config ${config.id}:`, error); + console.error({ + message: `Error updating Camoufox config ${config.id}`, + error, + }); return false; } } diff --git a/nodecar/src/proxy-worker.ts b/nodecar/src/proxy-worker.ts index 3b0e435..84357b1 100644 --- a/nodecar/src/proxy-worker.ts +++ b/nodecar/src/proxy-worker.ts @@ -31,28 +31,22 @@ export async function runProxyWorker(id: string): Promise { }); // Handle process termination gracefully - const gracefulShutdown = async (signal: string) => { - console.log(`Proxy worker ${id} received ${signal}, shutting down...`); + const gracefulShutdown = async () => { try { await server.close(true); - console.log(`Proxy worker ${id} shut down successfully`); - } catch (error) { - console.error(`Error during shutdown for proxy ${id}:`, error); - } + } catch {} process.exit(0); }; - process.on("SIGTERM", () => void gracefulShutdown("SIGTERM")); - process.on("SIGINT", () => void gracefulShutdown("SIGINT")); + process.on("SIGTERM", () => void gracefulShutdown()); + process.on("SIGINT", () => void gracefulShutdown()); // Handle uncaught exceptions - process.on("uncaughtException", (error) => { - console.error(`Uncaught exception in proxy worker ${id}:`, error); + process.on("uncaughtException", () => { process.exit(1); }); - process.on("unhandledRejection", (reason) => { - console.error(`Unhandled rejection in proxy worker ${id}:`, reason); + process.on("unhandledRejection", () => { process.exit(1); }); @@ -65,9 +59,6 @@ export async function runProxyWorker(id: string): Promise { config.localUrl = `http://127.0.0.1:${server.port}`; updateProxyConfig(config); - console.log(`Proxy worker ${id} started on port ${server.port}`); - console.log(`Forwarding to upstream proxy: ${config.upstreamUrl}`); - // Keep the process alive setInterval(() => { // Do nothing, just keep the process alive