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")