From: Alexander Moisseev Date: Fri, 10 Jul 2026 16:13:34 +0000 (+0300) Subject: [Fix] WebUI: route a malformed /stat response to the login dialog X-Git-Tag: 4.1.3~52^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f116cf0a85c93aacd8f8cf737979de35c126babe;p=thirdparty%2Frspamd.git [Fix] WebUI: route a malformed /stat response to the login dialog The connect probe swallowed JSON parse errors (parseJsonSafe returned {}), so a 2xx /stat with a non-JSON body (truncated by a proxy, a captive-portal page, corruption) loaded an empty, half-loaded main UI with a "Cannot get server status" alert and no login path. The former jQuery content-type parse raised parsererror and fell through to the login form. Parse the body explicitly and, on any failure, show the connect dialog — matching the pre-migration behaviour and covering the broad case (any non-JSON 2xx, not only application/json). Removes the now-unused parseJsonSafe helper. --- diff --git a/interface/js/app/rspamd.js b/interface/js/app/rspamd.js index c41cd288e5..5afd2bafd6 100644 --- a/interface/js/app/rspamd.js +++ b/interface/js/app/rspamd.js @@ -293,17 +293,6 @@ define(["app/common", "bootstrap", "visibility", }); } - - // Parse JSON, returning {} for an empty or non-JSON body (the /stat probe - // must not throw and strand the connect flow). - function parseJsonSafe(text) { - try { - return text ? JSON.parse(text) : {}; - } catch (err) { - return {}; - } - } - // Show the connect (login) dialog and wire its form submission. function showConnectDialog() { const connectDialog = document.getElementById("connectDialog"); @@ -385,9 +374,16 @@ define(["app/common", "bootstrap", "visibility", if (ajaxTimeout > 0) xhr.timeout = ajaxTimeout; xhr.onload = () => { if (xhr.status >= 200 && xhr.status < 300) { - const data = parseJsonSafe(xhr.responseText); - sessionStorage.setItem("read_only", data.read_only); - displayUI(); + try { + const data = JSON.parse(xhr.responseText); + sessionStorage.setItem("read_only", data.read_only); + displayUI(); + } catch (err) { + // A 2xx /stat whose body isn't JSON means a broken response + // (truncated by a proxy, a captive-portal page, etc.): show + // the login dialog rather than an empty, half-loaded UI. + showConnectDialog(); + } } else { showConnectDialog(); }