You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
buffer_platform/buffer_platform_v2/app/middleware.py

68 lines
2.4 KiB

"""全局中间件模块 - 异常处理与请求日志"""
import logging
import time
from fastapi import Request
from fastapi.responses import JSONResponse
from starlette.middleware.base import BaseHTTPMiddleware
logger = logging.getLogger(__name__)
class BusinessError(Exception):
"""业务逻辑异常基类。"""
def __init__(self, message: str, code: str = "BUSINESS_ERROR") -> None:
self.message = message
self.code = code
super().__init__(message)
class DataNotFoundError(BusinessError):
"""数据未找到异常。"""
def __init__(self, message: str = "数据不存在", code: str = "DATA_NOT_FOUND") -> None:
super().__init__(message=message, code=code)
class GlobalExceptionMiddleware(BaseHTTPMiddleware):
"""全局异常处理中间件 - 捕获 BusinessError / ValueError / Exception。"""
async def dispatch(self, request: Request, call_next):
start_time = time.time()
try:
response = await call_next(request)
return response
except BusinessError as exc:
logger.warning("业务异常: [%s] %s", exc.code, exc.message)
return JSONResponse(
status_code=400,
content={"success": False, "message": exc.message, "code": exc.code},
)
except ValueError as exc:
logger.warning("参数错误: %s", exc)
return JSONResponse(
status_code=422,
content={"success": False, "message": str(exc), "code": "VALIDATION_ERROR"},
)
except Exception as exc:
logger.exception("未预期的服务器错误: %s", exc)
return JSONResponse(
status_code=500,
content={"success": False, "message": "服务器内部错误", "code": "INTERNAL_ERROR"},
)
finally:
duration = time.time() - start_time
logger.info("%s %s %.3fs", request.method, request.url.path, duration)
class RequestLoggingMiddleware(BaseHTTPMiddleware):
"""请求日志中间件 - 记录每个请求的基本信息。"""
async def dispatch(self, request: Request, call_next):
logger.info("请求开始: %s %s", request.method, request.url.path)
response = await call_next(request)
logger.info("请求完成: %s %s -> %s", request.method, request.url.path, response.status_code)
return response