'use strict'; const http = require('http'); const { settings, validate } = require('./src/settings'); const { probeCycle, startProbing, stopProbing, } = require('./src/upstreams'); const { handleProxy } = require('./src/proxy'); const { healthPayload } = require('./src/health'); const { sendText, sendJson } = require('./src/http-utils'); const HEALTH_PATHS = new Set(['/health', '/healthz']); const server = http.createServer((req, res) => { let reqUrl; try { reqUrl = new URL(req.url, 'http://proxy.invalid'); } catch { sendText(res, 400, 'Bad request'); return; } if (req.method === 'GET' && HEALTH_PATHS.has(reqUrl.pathname)) { sendJson(res, 200, healthPayload()); return; } handleProxy(req, res, reqUrl); }); function shutdown(signal) { console.log(`Received ${signal}, shutting down`); stopProbing(); server.close(() => process.exit(0)); setTimeout(() => process.exit(0), 5000).unref(); } process.on('SIGTERM', () => shutdown('SIGTERM')); process.on('SIGINT', () => shutdown('SIGINT')); async function main() { try { validate(); } catch (e) { console.error(e.message); process.exit(1); } await probeCycle(); server.listen(settings.listenPort, () => { console.log(`Xtream proxy listening on :${settings.listenPort}`); console.log(`Config file: ${settings.configFile}`); console.log( `Probe interval: ${settings.probeIntervalSec}s, probe timeout: ${settings.probeTimeoutMs}ms` ); startProbing(); }); } main().catch((e) => { console.error(e); process.exit(1); });