From 9a9d8a7761b4983bba91fe411d51e12fa0066066 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 20 Aug 2026 21:38:25 +0000 Subject: [PATCH] =?UTF-8?q?Client-debug:=20=D0=BB=D0=BE=D0=B3=D0=B8=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20fetch=20=D0=B2=20/api/v1?= =?UTF-8?q?/debug/log?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/js/api.js | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/public/js/api.js b/public/js/api.js index 4413fb4..95a1ac0 100644 --- a/public/js/api.js +++ b/public/js/api.js @@ -54,11 +54,24 @@ async function api(path, opts = {}, _retry = 0) { // timeout 15s — иначе UI висит вечно const controller = new AbortController(); const tid = setTimeout(() => controller.abort(), 15000); + const t0 = Date.now(); try { r = await fetch(API_BASE + path, { ...o, signal: controller.signal }); } catch (networkErr) { clearTimeout(tid); - console.warn('fetch network error:', networkErr); + const ms = Date.now() - t0; + console.warn('fetch network error:', networkErr, 'ms:', ms); + // детальный лог на сервер для дебага + try { + fetch(API_BASE + '/api/v1/debug/log', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + path, status: 0, ms, ua: navigator.userAgent, err: String(networkErr), isTelegram: !!(window.Telegram && window.Telegram.WebApp), + }), + keepalive: true, + }).catch(() => {}); + } catch {} if (networkErr.name === 'AbortError') { throw new Error('Сервер не отвечает (таймаут 15с)'); } @@ -69,6 +82,18 @@ async function api(path, opts = {}, _retry = 0) { throw new Error('Нет связи с сервером'); } clearTimeout(tid); + const ms = Date.now() - t0; + // логируем всё на сервер для отладки с iOS + try { + fetch(API_BASE + '/api/v1/debug/log', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + path, status: r.status, ms, ua: navigator.userAgent.substring(0, 80), isTelegram: !!(window.Telegram && window.Telegram.WebApp), + }), + keepalive: true, + }).catch(() => {}); + } catch {} if (r.status === 401 && Store.refresh && !opts._isRefresh) { try { const r2 = await fetch(API_BASE + '/api/v1/auth/refresh', {