'Unauthorized', 'code' => 401]); exit; } } } if ($endpoint !== 'auth') session_write_close(); $body = file_get_contents('php://input'); $data = json_decode($body, true) ?? []; // ── Fast ping (no file dispatch needed) ────────────────────────────── if ($endpoint === 'ping') { echo json_encode(['status' => 'online', 'time' => date('c'), 'codename' => JARVIS_CODENAME]); exit; } // ── Endpoint → file map ─────────────────────────────────────────────── $endpoints = [ 'auth' => 'auth.php', 'chat' => 'chat.php', 'system' => 'system.php', 'netscan' => 'netscan.php', 'network' => 'network.php', 'proxmox' => 'proxmox.php', 'ha' => 'ha.php', 'tts' => 'tts.php', 'email' => 'email.php', 'do' => 'do_server.php', 'alerts' => 'alerts.php', 'facts' => 'facts_collector.php', 'weather' => 'weather.php', 'news' => 'news.php', 'sites' => 'sites.php', 'agent' => 'agent.php', 'planner' => 'planner.php', 'arc' => 'arc.php', 'directives' => 'directives.php', 'memory' => 'memory.php', 'calendar' => 'calendar_sync.php', ]; if (!isset($endpoints[$endpoint])) { http_response_code(404); echo json_encode(['error' => 'Unknown endpoint: ' . $endpoint]); exit; } $file = __DIR__ . '/../api/endpoints/' . $endpoints[$endpoint]; // ── Fault-isolated dispatch ─────────────────────────────────────────── // ob_start() buffers any partial output so a mid-execution fatal doesn't // send a broken response. catch(Throwable) catches ParseError, TypeError, // and all other Errors + Exceptions in PHP 7+. ob_start(); try { require $file; ob_end_flush(); } catch (\Throwable $e) { ob_end_clean(); http_response_code(500); echo json_encode(['error' => 'Endpoint unavailable', 'endpoint' => $endpoint, 'code' => 500]); error_log(sprintf('JARVIS API [%s] %s: %s in %s:%d', $endpoint, get_class($e), $e->getMessage(), $e->getFile(), $e->getLine() )); }