import time from fastapi import Request, Response from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint from services.logging import LogService from models.database import UserAccount import jwt from jwt.exceptions import InvalidTokenError from services.auth import ALGORITHM from services.config import ConfigCenter class LoggingMiddleware(BaseHTTPMiddleware): async def dispatch(self, request: Request, call_next: RequestResponseEndpoint) -> Response: start_time = time.time() user_id = None if "authorization" in request.headers: token_str = request.headers.get("authorization") try: if token_str and token_str.startswith("Bearer "): token = token_str.split(" ")[1] payload = jwt.decode(token, ConfigCenter.get_secret_key("SECRET_KEY"), algorithms=[ALGORITHM]) username = payload.get("sub") if username: user_account = await UserAccount.get_or_none(username=username) if user_account: user_id = user_account.id except (InvalidTokenError, Exception): pass response = await call_next(request) process_time = (time.time() - start_time) * 1000 details = { "client_ip": request.client.host, "method": request.method, "path": request.url.path, "headers": dict(request.headers), "status_code": response.status_code, "process_time_ms": round(process_time, 2) } message = f"{request.method} {request.url.path} - {response.status_code}" await LogService.api(message, details, user_id) return response