const WebSocket = require('ws'); const axios = require('axios'); require('dotenv').config(); const WS_URL = process.env.WS_URL; if (!WS_URL) { console.error('❌ WS_URL is not set in .env'); process.exit(1); } let ws = null; let reconnectAttempts = 0; const INITIAL_BACKOFF = 2000; // 2 seconds function connect() { console.log(`🔄 Connecting to ${WS_URL}...`); ws = new WebSocket(WS_URL); ws.on('open', () => { console.log('✅ Remote Agent connected to NetAnalyzer'); reconnectAttempts = 0; }); ws.on('message', async (data) => { try { const request = JSON.parse(data); if (request.action !== 'proxyRequest') return; console.log(`🔄 Proxying ${request.method || 'GET'} ${request.url}`); const response = await axios({ method: request.method || 'GET', url: request.url, headers: request.headers || {}, auth: request.auth || undefined, data: request.body || undefined, timeout: 30000, }); ws.send(JSON.stringify({ requestId: request.requestId, status: response.status, data: response.data, headers: response.headers })); } catch (err) { console.error('Proxy error:', err.message); ws.send(JSON.stringify({ requestId: request.requestId, error: err.message, status: err.response?.status || 500, data: err.response?.data || null })); } }); ws.on('close', (code, reason) => { console.log(`❌ Disconnected (code: ${code}). Reconnecting...`); scheduleReconnect(); }); ws.on('error', (err) => { console.error('WebSocket error:', err.message); }); } function scheduleReconnect() { reconnectAttempts++; // Exponential backoff, capped at 60 seconds const backoff = Math.min(INITIAL_BACKOFF * Math.pow(1.5, reconnectAttempts - 1), 60000); console.log(`⏳ Reconnecting in ${Math.round(backoff/1000)}s... (attempt ${reconnectAttempts})`); setTimeout(() => { connect(); }, backoff); } // Start initial connection connect(); // Graceful shutdown process.on('SIGINT', () => { console.log('🛑 Shutting down remote agent...'); if (ws) ws.close(); process.exit(0); });