From efb9eefed6cf9391e46d704243f85e4509199350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Mon, 29 Jun 2026 16:45:39 +0400 Subject: [PATCH] docs: Opus HTTP2 protocol error diagnostic --- .../opus-drhider-http2-error-2026-06-29.md | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 History/opus-drhider-http2-error-2026-06-29.md diff --git a/History/opus-drhider-http2-error-2026-06-29.md b/History/opus-drhider-http2-error-2026-06-29.md new file mode 100644 index 0000000..5971beb --- /dev/null +++ b/History/opus-drhider-http2-error-2026-06-29.md @@ -0,0 +1,60 @@ +# Opus — ERR_HTTP2_PROTOCOL_ERROR на DrHider + +29.06.2026 + +## Симптом + +Браузер: `POST /api/drhider` → `net::ERR_HTTP2_PROTOCOL_ERROR` + +curl с сервера (Linux): работает, HTTP/2, 200 OK. +Браузер пользователя (Windows, Chrome 144): ERR_HTTP2_PROTOCOL_ERROR. + +## Архитектура + +``` +Browser → Nubes Managed Python → gunicorn (1 worker, --timeout 300) → Flask app +``` + +Dockerfile: +``` +CMD ["gunicorn", "--bind", "0.0.0.0:5000", "--timeout", "300", "--workers", "1", "site.app:app"] +``` + +## Код обработчика + +```python +@app.route("/api/drhider", methods=["POST"]) +def api_drhider(): + from services.drhider import obfuscate_files + uploaded = request.files.getlist("files") + ... + job_id = uuid.uuid4().hex + _drhider_jobs[job_id] = {"done": False, "data": None, "error": None} + + def _process(): + try: + from services.llm_client import HttpxLLMClient + llm = HttpxLLMClient(LLM_URL, LLM_KEY, LLM_MODEL) if LLM_KEY else None + zip_data, _csv = obfuscate_files(files, llm_client=llm) + _drhider_jobs[job_id] = {"done": True, "data": zip_data, "error": None} + except Exception as e: + _drhider_jobs[job_id] = {"done": True, "data": None, "error": str(e)} + + threading.Thread(target=_process, daemon=True).start() + return jsonify({"ok": True, "job_id": job_id}) +``` + +## Что известно + +1. curl работает (HTTP/2, 200, возвращает `{"job_id":"...","ok":true}`) +2. Браузер — ERR_HTTP2_PROTOCOL_ERROR +3. Мелкие файлы и большие — одинаково +4. До перехода на gunicorn + threading — была та же ошибка? (не уверен) + +## Вопросы + +1. Может ли `threading.Thread` внутри Flask/gunicorn вызывать ERR_HTTP2_PROTOCOL_ERROR? +2. Может ли проблема быть в том, что gunicorn с 1 worker не поддерживает HTTP/2 должным образом? +3. Нужно ли добавить `--worker-class` к gunicorn (gevent/eventlet) для HTTP/2? +4. Может ли Nubes-прокси перед managed-сервисом вызывать эту ошибку? +5. Что попробовать в первую очередь?