""" API日志中间件 """ import time from fastapi import Request from starlette.middleware.base import BaseHTTPMiddleware from sqlalchemy.orm import Session from app.database import SessionLocal from app.models.api_log import APILog from app.core.logger import logger from datetime import datetime class APILoggingMiddleware(BaseHTTPMiddleware): """API日志中间件""" async def dispatch(self, request: Request, call_next): start_time = time.time() # 获取请求信息 method = request.method url = str(request.url) client_ip = request.client.host if request.client else None user_agent = request.headers.get("user-agent", "") # 获取请求体(如果是POST/PUT),其它方法不修改url request_body = "" if method in ["POST", "PUT", "PATCH"]: try: body = await request.body() request_body = body.decode('utf-8')[:1000] # 限制长度 except: pass # 执行请求 response = await call_next(request) # 计算执行时间 execution_time = int((time.time() - start_time) * 1000) # 获取响应状态码 status_code = response.status_code # 异步记录日志(避免阻塞) try: db = SessionLocal() try: api_log = APILog( endpoint=url, method=method, request_data=request_body, ip_address=client_ip, user_agent=user_agent, response_code=status_code, execution_time=execution_time, created_at=datetime.now() ) db.add(api_log) db.commit() except Exception as e: db.rollback() logger.error(f"记录API日志失败: {e}") finally: db.close() except: pass return response