diff --git a/app/sovran_systemsos_web/server.py b/app/sovran_systemsos_web/server.py index 6500e7e..ffafebd 100644 --- a/app/sovran_systemsos_web/server.py +++ b/app/sovran_systemsos_web/server.py @@ -87,7 +87,7 @@ LOGIN_FAIL_WINDOW = 60.0 # rolling window (seconds) for counting failures LOGIN_FAIL_MAX = 10 # max failures in window before extra delay # Public paths that are accessible without a valid session -_AUTH_EXEMPT_PATHS = {"/login", "/api/login", "/api/updates/status", "/api/rebuild/status", "/auto-login"} +_AUTH_EXEMPT_PATHS = {"/login", "/api/login", "/api/updates/status", "/api/rebuild/status", "/auto-login", "/api/ping"} # Prefixes for static assets required by the login page _AUTH_EXEMPT_PREFIXES = ("/static/css/", "/static/sovran-hub-icon.svg") @@ -2596,6 +2596,11 @@ async def api_updates_check(): return {"available": available is not False} +@app.get("/api/ping") +async def api_ping(): + return {"ok": True} + + @app.post("/api/reboot") async def api_reboot(): try: diff --git a/app/sovran_systemsos_web/static/js/security.js b/app/sovran_systemsos_web/static/js/security.js index 3a92efd..f17eda1 100644 --- a/app/sovran_systemsos_web/static/js/security.js +++ b/app/sovran_systemsos_web/static/js/security.js @@ -161,6 +161,8 @@ function openSecurityModal() { rebootBtn.disabled = true; rebootBtn.textContent = "Rebooting\u2026"; if ($rebootOverlay) $rebootOverlay.classList.add("visible"); + _rebootStartTime = Date.now(); + _serverWentDown = false; setTimeout(waitForServerReboot, REBOOT_INITIAL_DELAY); var rebootCtrl = new AbortController(); setTimeout(function() { rebootCtrl.abort(); }, REBOOT_REQUEST_TIMEOUT); diff --git a/app/sovran_systemsos_web/static/js/update.js b/app/sovran_systemsos_web/static/js/update.js index a109612..2a7ce7f 100644 --- a/app/sovran_systemsos_web/static/js/update.js +++ b/app/sovran_systemsos_web/static/js/update.js @@ -185,21 +185,19 @@ function waitForServerReboot() { var controller = new AbortController(); var timeoutId = setTimeout(function() { controller.abort(); }, REBOOT_FETCH_TIMEOUT); - fetch("/api/config", { cache: "no-store", signal: controller.signal, headers: { "Connection": "close" } }) + fetch("/api/ping", { cache: "no-store", signal: controller.signal, headers: { "Connection": "close" } }) .then(function(res) { clearTimeout(timeoutId); - if (res.ok && _serverWentDown) { - // Server is back after having been down — reboot is complete + if (_serverWentDown) { + // Server is responding after having been down — reboot is complete. + // Any response (even 401/500) means the server process is back. window.location.reload(); - } else if (res.ok && !_serverWentDown && (Date.now() - _rebootStartTime) < 90000) { + } else if ((Date.now() - _rebootStartTime) < 90000) { // Server still responding but hasn't gone down yet — keep waiting setTimeout(waitForServerReboot, REBOOT_CHECK_INTERVAL); - } else if (res.ok) { + } else { // Been over 90 seconds and server is responding — just reload window.location.reload(); - } else { - _serverWentDown = true; - setTimeout(waitForServerReboot, REBOOT_CHECK_INTERVAL); } }) .catch(function() {