refactor(server): clean main.py — remove duplicate imports, dead code, unify logging, fix proxy lifecycle
This commit is contained in:
+20
-31
@@ -1,30 +1,23 @@
|
|||||||
import re
|
import re
|
||||||
from fastapi import Depends, FastAPI, HTTPException, Request, Response
|
|
||||||
from fastapi.responses import FileResponse, JSONResponse
|
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
|
from datetime import datetime
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
|
import httpx
|
||||||
import json
|
import json
|
||||||
import structlog
|
import structlog
|
||||||
from cachetools import TTLCache
|
from cachetools import TTLCache
|
||||||
import logging
|
from fastapi import Depends, FastAPI, HTTPException, Request, Response
|
||||||
from datetime import datetime
|
from fastapi.responses import FileResponse, JSONResponse
|
||||||
from uvicorn.protocols.http.httptools_impl import HttpToolsProtocol
|
from uvicorn.protocols.http.httptools_impl import HttpToolsProtocol
|
||||||
|
|
||||||
from cachetools import TTLCache
|
|
||||||
from urllib.parse import urlparse
|
|
||||||
|
|
||||||
from pack_manager import DATA_DIR, scan_pack, get_cached_manifest, PACKS_DIR
|
from pack_manager import DATA_DIR, scan_pack, get_cached_manifest, PACKS_DIR
|
||||||
from models import PackMeta
|
from models import PackMeta
|
||||||
from middleware import LoggingMiddleware
|
from middleware import LoggingMiddleware
|
||||||
from cli import parse_args, run_test_mode, run_production_mode, run_development_mode
|
from cli import parse_args, run_test_mode, run_production_mode, run_development_mode
|
||||||
from log_manager import init_logging
|
from log_manager import init_logging
|
||||||
|
|
||||||
from fastapi.responses import Response
|
|
||||||
|
|
||||||
import httpx
|
|
||||||
import base64
|
|
||||||
from fastapi.responses import StreamingResponse
|
|
||||||
|
|
||||||
from auth import get_current_user, router as auth_router, init_db, verify_jwt
|
from auth import get_current_user, router as auth_router, init_db, verify_jwt
|
||||||
from roles import Permissions, has_permission
|
from roles import Permissions, has_permission
|
||||||
from admin_router import router as admin_router
|
from admin_router import router as admin_router
|
||||||
@@ -43,7 +36,6 @@ async def lifespan(app: FastAPI):
|
|||||||
|
|
||||||
# Initialize logging
|
# Initialize logging
|
||||||
init_logging()
|
init_logging()
|
||||||
#logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
# Determine environment
|
# Determine environment
|
||||||
if args.test:
|
if args.test:
|
||||||
@@ -60,8 +52,6 @@ async def lifespan(app: FastAPI):
|
|||||||
PACKS_DIR.mkdir(exist_ok=True)
|
PACKS_DIR.mkdir(exist_ok=True)
|
||||||
DATA_DIR.mkdir(exist_ok=True)
|
DATA_DIR.mkdir(exist_ok=True)
|
||||||
|
|
||||||
BLOCKED_HOSTS = []
|
|
||||||
|
|
||||||
init_db()
|
init_db()
|
||||||
|
|
||||||
if args.test:
|
if args.test:
|
||||||
@@ -84,7 +74,17 @@ async def lifespan(app: FastAPI):
|
|||||||
logger.error(f"Failed to scan pack: {pack_dir.name} - {e}", exc_info=True)
|
logger.error(f"Failed to scan pack: {pack_dir.name} - {e}", exc_info=True)
|
||||||
|
|
||||||
logger.info("All packs ready. Server is running.")
|
logger.info("All packs ready. Server is running.")
|
||||||
|
|
||||||
|
# Initialize proxy client
|
||||||
|
global proxy_client
|
||||||
|
proxy_client = httpx.AsyncClient(timeout=60.0, follow_redirects=True)
|
||||||
|
|
||||||
yield
|
yield
|
||||||
|
|
||||||
|
# Cleanup proxy client
|
||||||
|
if proxy_client:
|
||||||
|
await proxy_client.aclose()
|
||||||
|
|
||||||
logger.info("Server shutting down...")
|
logger.info("Server shutting down...")
|
||||||
|
|
||||||
|
|
||||||
@@ -432,9 +432,7 @@ def patched_data_received(self, data):
|
|||||||
return original_data_received(self, data)
|
return original_data_received(self, data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
client = self.transport.get_extra_info('peername')
|
client = self.transport.get_extra_info('peername')
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
# Показываем первые 200 байт запроса в HEX для диагностики
|
|
||||||
hex_preview = data[:100].hex() if len(data) > 0 else "empty"
|
hex_preview = data[:100].hex() if len(data) > 0 else "empty"
|
||||||
|
|
||||||
logger.error(f"Invalid HTTP request from {client}")
|
logger.error(f"Invalid HTTP request from {client}")
|
||||||
@@ -444,16 +442,14 @@ def patched_data_received(self, data):
|
|||||||
try:
|
try:
|
||||||
raw_data = data[:500].decode('utf-8', errors='replace')
|
raw_data = data[:500].decode('utf-8', errors='replace')
|
||||||
logger.error(f"Raw request data: {repr(raw_data)}")
|
logger.error(f"Raw request data: {repr(raw_data)}")
|
||||||
except:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Не перевыбрасываем исключение, а возвращаем 400 ответ
|
|
||||||
# Это важно! Иначе клиент не получит ответ
|
|
||||||
try:
|
try:
|
||||||
response = b"HTTP/1.1 400 Bad Request\r\nContent-Type: text/plain\r\nContent-Length: 21\r\n\r\nInvalid HTTP request"
|
response = b"HTTP/1.1 400 Bad Request\r\nContent-Type: text/plain\r\nContent-Length: 21\r\n\r\nInvalid HTTP request"
|
||||||
self.transport.write(response)
|
self.transport.write(response)
|
||||||
self.transport.close()
|
self.transport.close()
|
||||||
except:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -465,7 +461,6 @@ HttpToolsProtocol.data_received = patched_data_received
|
|||||||
@app.get("/")
|
@app.get("/")
|
||||||
async def root():
|
async def root():
|
||||||
"""Root endpoint"""
|
"""Root endpoint"""
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
logger.info("Root endpoint accessed")
|
logger.info("Root endpoint accessed")
|
||||||
return {
|
return {
|
||||||
"status": "ok",
|
"status": "ok",
|
||||||
@@ -856,8 +851,8 @@ async def get_launcher_full_info():
|
|||||||
# Эти эндпоинты позволяют клиентам с сетевыми проблемами
|
# Эти эндпоинты позволяют клиентам с сетевыми проблемами
|
||||||
# скачивать файлы через сервер Zern
|
# скачивать файлы через сервер Zern
|
||||||
|
|
||||||
# Создаем HTTP клиент для прокси
|
# HTTP клиент для прокси — создаётся в lifespan, закрывается при shutdown
|
||||||
proxy_client = httpx.AsyncClient(timeout=60.0, follow_redirects=True)
|
proxy_client: httpx.AsyncClient | None = None
|
||||||
|
|
||||||
# Кэш для часто запрашиваемых данных (5 минут)
|
# Кэш для часто запрашиваемых данных (5 минут)
|
||||||
proxy_cache = TTLCache(maxsize=50, ttl=300)
|
proxy_cache = TTLCache(maxsize=50, ttl=300)
|
||||||
@@ -1192,12 +1187,6 @@ async def global_exception_handler(request: Request, exc: Exception):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# Cleanup on shutdown
|
|
||||||
@app.on_event("shutdown")
|
|
||||||
async def shutdown_proxy():
|
|
||||||
await proxy_client.close()
|
|
||||||
|
|
||||||
|
|
||||||
# ====================== ЗАПУСК ======================
|
# ====================== ЗАПУСК ======================
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
Reference in New Issue
Block a user