Add robust JSON parsing for server status and implement retry logic for fetching

This commit is contained in:
Fabian Schieder 2026-03-01 14:46:04 +01:00
parent 0e15466eee
commit 38ec4da90d

View File

@ -104,6 +104,19 @@ document.querySelectorAll('.card').forEach(card => {
return String(url).replace(/\/+$/, ''); return String(url).replace(/\/+$/, '');
}; };
const parsePossiblyUtf16Json = (text) => {
if (!text) return null;
// If server accidentally delivered UTF-16LE bytes, the browser may decode it with lots of \u0000.
// Remove NULs and common BOM remnants.
const cleaned = String(text)
.replace(/^\uFEFF/, '')
.replace(/\u0000/g, '')
.trim();
return JSON.parse(cleaned);
};
const applyPayload = (payload) => { const applyPayload = (payload) => {
const byUrl = payload && payload.byUrl ? payload.byUrl : {}; const byUrl = payload && payload.byUrl ? payload.byUrl : {};
const byUrlNormalized = payload && payload.byUrlNormalized ? payload.byUrlNormalized : {}; const byUrlNormalized = payload && payload.byUrlNormalized ? payload.byUrlNormalized : {};
@ -136,15 +149,19 @@ document.querySelectorAll('.card').forEach(card => {
const fetchAndApply = async () => { const fetchAndApply = async () => {
const res = await fetch('/server_status.php', { cache: 'no-store' }); const res = await fetch('/server_status.php', { cache: 'no-store' });
if (!res.ok) throw new Error('status_fetch_failed'); if (!res.ok) throw new Error('status_fetch_failed');
const payload = await res.json();
// Use text() + robust JSON parse to survive wrong encoding (UTF-16/NULs).
const text = await res.text();
const payload = parsePossiblyUtf16Json(text);
if (!payload) throw new Error('status_json_empty');
applyPayload(payload); applyPayload(payload);
}; };
// Ziel: nach ~1s sichtbar springen (nicht sofort beim ersten Paint). // Nach ~1s einmal aktualisieren, dann (falls nötig) 2 schnelle Retries.
// Falls der Endpoint kurz hängt, probieren wir 1-2x nochmal. const delays = [1000, 1000, 1500];
const attempts = [1000, 2000, 3500]; for (const d of delays) {
for (let i = 0; i < attempts.length; i++) { await new Promise(r => setTimeout(r, d));
await new Promise(r => setTimeout(r, attempts[i]));
try { try {
await fetchAndApply(); await fetchAndApply();
break; break;