From e3e850d4b209848b449543bf354d84a7ade0f569 Mon Sep 17 00:00:00 2001 From: Kavalar Date: Thu, 17 Sep 2026 23:24:14 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A3=D1=81=D1=82=D0=BE=D0=B9=D1=87=D0=B8?= =?UTF-8?q?=D0=B2=D0=BE=D1=81=D1=82=D1=8C=20=D0=BA=20HTML-=D0=BE=D1=82?= =?UTF-8?q?=D0=B2=D0=B5=D1=82=D0=B0=D0=BC:=20JSON-=D0=BE=D0=B1=D1=80=D0=B0?= =?UTF-8?q?=D0=B1=D0=BE=D1=82=D1=87=D0=B8=D0=BA=D0=B8=20=D0=BE=D1=88=D0=B8?= =?UTF-8?q?=D0=B1=D0=BE=D0=BA=20(413/404/500),=20=D0=B1=D0=B5=D0=B7=D0=BE?= =?UTF-8?q?=D0=BF=D0=B0=D1=81=D0=BD=D1=8B=D0=B9=20=D1=80=D0=B0=D0=B7=D0=B1?= =?UTF-8?q?=D0=BE=D1=80=20=D0=BE=D1=82=D0=B2=D0=B5=D1=82=D0=B0=20=D0=BD?= =?UTF-8?q?=D0=B0=20=D1=84=D1=80=D0=BE=D0=BD=D1=82=D0=B5=D0=BD=D0=B4=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.py | 24 +++++++++++++++++++++++- templates/index.html | 15 +++++++++++++-- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/app.py b/app.py index 7cbfb5c..fc67542 100644 --- a/app.py +++ b/app.py @@ -109,6 +109,24 @@ BASE_URL = os.environ.get("BASE_URL", "https://med.my-dpr.ru").rstrip("/") CORS_ORIGINS = [o.strip() for o in os.environ.get("CORS_ORIGINS", "*").split(",") if o.strip()] +# Обработчики ошибок: всегда возвращаем JSON, чтобы фронтенд +# не получал HTML-страницу (иначе response.json() падает с "Unexpected token '<'"). +@app.errorhandler(413) +def too_large(e): + return jsonify({"error": "Видео слишком большое (максимум 100 МБ)"}), 413 + + +@app.errorhandler(404) +def not_found(e): + return jsonify({"error": "Не найдено"}), 404 + + +@app.errorhandler(500) +def server_error(e): + logger.error(f"Необработанная ошибка: {e}") + return jsonify({"error": "Внутренняя ошибка сервера"}), 500 + + @app.after_request def add_cors_headers(response): origin = request.headers.get("Origin") @@ -470,7 +488,11 @@ def analyze(): os.makedirs(work_dir, exist_ok=True) video_path = os.path.join(work_dir, f"input{ext}") - video.save(video_path) + try: + video.save(video_path) + except Exception as e: + logger.error(f"[{job_id}] Ошибка сохранения видео: {e}") + return jsonify({"error": f"Не удалось сохранить видео: {e}"}), 500 # Сохраняем копию записанного видео (то, что было в кружке) — даже если анализ упадёт saved_video = os.path.join(VIDEO_DIR, f"{job_id}{ext}") diff --git a/templates/index.html b/templates/index.html index 2c85fc2..0025766 100644 --- a/templates/index.html +++ b/templates/index.html @@ -483,6 +483,17 @@ resultCard.style.display = 'none'; setProgress(5, 'Загрузка видео...'); + // Безопасный разбор ответа: если сервер вернул не JSON (например, + // HTML-страницу ошибки), не падаем с "Unexpected token '<'". + async function parseJson(response) { + const ct = (response.headers.get('content-type') || '').toLowerCase(); + if (ct.includes('application/json')) { + return await response.json(); + } + const text = await response.text(); + return { error: text || `Ошибка сервера (HTTP ${response.status})` }; + } + const formData = new FormData(); formData.append('video', blob, filename); @@ -496,14 +507,14 @@ }); if (!response.ok) { - const err = await response.json(); + const err = await parseJson(response); const e = new Error(err.error || 'Ошибка анализа'); e.videoUrl = err.video_url; throw e; } setProgress(90, 'Формирование результата...'); - const data = await response.json(); + const data = await parseJson(response); if (data.error) { showError(data.error);