diff --git a/dashcaddy-api/src/app.js b/dashcaddy-api/src/app.js index 2a0cf46..e7f1b34 100644 --- a/dashcaddy-api/src/app.js +++ b/dashcaddy-api/src/app.js @@ -30,7 +30,7 @@ const healthChecker = require('../health-checker'); const updateManager = require('../update-manager'); const selfUpdater = require('../self-updater'); const configureMiddleware = require('../middleware'); -const { validateStartupConfig, syncHealthCheckerServices } = require('../startup-validator'); +const { syncHealthCheckerServices } = require('../startup-validator'); const { CSRF_HEADER_NAME } = require('../csrf-protection'); const { resolveServiceUrl } = require('../url-resolver'); const metrics = require('../metrics'); @@ -86,7 +86,7 @@ const { APP } = require('../constants'); /** * Create and configure the Express application */ -async function createApp() { +function createApp() { const app = express(); // Initialize logging @@ -161,7 +161,7 @@ async function createApp() { return first === 100 && second >= 64 && second <= 127; } - async function getTailscaleStatus() { + function getTailscaleStatus() { // Stub for now - will be populated by context return null; } @@ -211,7 +211,7 @@ async function createApp() { async function readConfig() { const { readJsonFile } = require('../fs-helpers'); - return readJsonFile(config.CONFIG_FILE, {}); + return await readJsonFile(config.CONFIG_FILE, {}); } async function saveConfig(updates) { @@ -244,7 +244,9 @@ async function createApp() { // Stub - will be implemented } - async function resyncHealthChecker() { + // Forwards the promise from syncHealthCheckerServices — intentionally not + // `async` since there is no `await` inside. Callers use `.catch()` on it. + function resyncHealthChecker() { return syncHealthCheckerServices({ log, SERVICES_FILE: config.SERVICES_FILE, @@ -629,10 +631,33 @@ async function createApp() { res.status(statusCode).send(); }, 'probe')); + // Scan OS network interfaces and classify the first LAN + Tailscale IPv4 + // addresses. Extracted to keep the route handler below ESLint's max-depth. + function detectInterfaceIps() { + const os = require('os'); + const LAN_RANGE = /^(192\.168\.|10\.|172\.(1[6-9]|2[0-9]|3[0-1])\.)/; + const all = []; + let lan = null; + let tailscale = null; + const interfaces = os.networkInterfaces(); + for (const [name, addrs] of Object.entries(interfaces)) { + for (const addr of addrs || []) { + if (addr.internal || addr.family !== 'IPv4') continue; + const { address: ip } = addr; + all.push({ name, ip }); + if (!tailscale && ip.startsWith('100.')) { + tailscale = ip; + } else if (!lan && LAN_RANGE.test(ip)) { + lan = ip; + } + } + } + return { lan, tailscale, all }; + } + // Network IPs endpoint app.get('/api/v1/network/ips', (req, res) => { try { - const os = require('os'); const envLan = process.env.HOST_LAN_IP; const envTailscale = process.env.HOST_TAILSCALE_IP; @@ -644,20 +669,10 @@ async function createApp() { }; if (!envLan || !envTailscale) { - const interfaces = os.networkInterfaces(); - for (const [name, addrs] of Object.entries(interfaces)) { - for (const addr of addrs) { - if (addr.internal || addr.family !== 'IPv4') continue; - const ip = addr.address; - result.all.push({ name, ip }); - - if (!result.tailscale && ip.startsWith('100.')) { - result.tailscale = ip; - } else if (!result.lan && (ip.startsWith('192.168.') || ip.startsWith('10.') || ip.match(/^172\.(1[6-9]|2[0-9]|3[0-1])\./))) { - result.lan = ip; - } - } - } + const detected = detectInterfaceIps(); + if (!result.lan) result.lan = detected.lan; + if (!result.tailscale) result.tailscale = detected.tailscale; + result.all = detected.all; } res.json(result);