From 6387292448ebe3b80c29c78e1cbd102bf7d9ec8a Mon Sep 17 00:00:00 2001 From: host Date: Sat, 25 Jul 2026 00:31:27 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D1=84=D0=B0=D0=B9=D0=BB=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/routers/console.py | 33 +++++++-------------------------- 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/backend/app/routers/console.py b/backend/app/routers/console.py index cb30c31..298f296 100644 --- a/backend/app/routers/console.py +++ b/backend/app/routers/console.py @@ -8,11 +8,12 @@ - Cookie PVEAuthCookie — если заданы PVE_USERNAME + PVE_PASSWORD 3. Проксирует бинарный VNC-поток между браузером клиента и Proxmox. -Особенности Proxmox: +Особенности: - В Proxmox 8.x+ vncticket может содержать спецсимволы (#, /, %, :), - которые ломают парсинг URL (RFC 3986). Кодируем их через quote(). - - PVE может вернуть HTTP redirect (302) на `https://...` вместо `wss://...`; - перехватываем и переписываем scheme через process_redirect. + которые ломают парсинг URL (RFC 3986). Кодируем через quote(). + - process_redirect в websockets не работает на uvloop (используется + uvicorn[standard]), поэтому редиректы не обрабатываем — Proxmox + обычно их и не делает при корректном URL. """ import asyncio @@ -22,7 +23,6 @@ from urllib.parse import quote import httpx import websockets -from websockets.http11 import Response from fastapi import APIRouter, Query, WebSocket, WebSocketDisconnect from ..config import settings @@ -32,23 +32,6 @@ logger = logging.getLogger(__name__) router = APIRouter(prefix="/console", tags=["console"]) -def _process_redirect(request, response: Response) -> Optional[str]: - """Перехватывает HTTP-redirect от Proxmox и переписывает https://→wss://. - - Proxmox иногда возвращает Location со схемой https:// (хотя для WebSocket - положено wss://). Библиотека websockets в этом случае падает с - InvalidURI("scheme isn't ws or wss"). Возвращаем исправленный URL. - """ - location = response.headers.get("Location", "") - if not location: - return None - if location.startswith("https://"): - return "wss://" + location[len("https://"):] - if location.startswith("http://"): - return "ws://" + location[len("http://"):] - return location - - async def _get_pve_auth_cookie() -> Optional[Tuple[str, str]]: """Аутентифицируется в Proxmox по логину/паролю и возвращает (cookie_header, csrf_token). @@ -94,9 +77,8 @@ async def console_ws( guest_path = "qemu" if guest_type == "vm" else "lxc" pve_host_only = settings.pve_host.replace("http://", "").replace("https://", "") - # quote() экранирует спецсимволы в тикете и порте по правилам RFC 3986, - # не затрагивая уже экранированные символы. Без этого в Proxmox 8.x+ - # vncticket может содержать # / % : которые ломают URL. + # quote() экранирует спецсимволы в тикете и порте по правилам RFC 3986. + # Без этого в Proxmox 8.x+ vncticket может содержать # / % : которые ломают URL. safe_ticket = quote(ticket, safe="") safe_port = quote(str(port), safe="") upstream_url = ( @@ -129,7 +111,6 @@ async def console_ws( extra_headers=headers, subprotocols=["binary"], ssl=None if settings.pve_verify_ssl else False, - process_redirect=_process_redirect, ) as upstream: logger.info("console_ws: upstream connected")