import logging from fastapi import FastAPI, Request from fastapi.exceptions import RequestValidationError from fastapi.responses import JSONResponse from sqlalchemy.exc import SQLAlchemyError from app.core.exceptions import AppError logger = logging.getLogger(__name__) def register_exception_handlers(app: FastAPI) -> None: """异常注册:把业务异常转换为统一响应格式。""" @app.exception_handler(AppError) async def handle_app_error(request: Request, exc: AppError) -> JSONResponse: logger.warning( "business_error code=%s path=%s user_id=%s", exc.code, request.url.path, request.headers.get("X-User-Id"), ) return JSONResponse( status_code=exc.status_code, content={"code": exc.code, "message": exc.message, "data": None}, ) @app.exception_handler(RequestValidationError) async def handle_validation_error(request: Request, exc: RequestValidationError) -> JSONResponse: logger.warning( "validation_error path=%s user_id=%s errors=%s", request.url.path, request.headers.get("X-User-Id"), exc.errors(), ) return JSONResponse( status_code=422, content={"code": "VALIDATION_ERROR", "message": "request validation failed", "data": {"errors": exc.errors()}}, ) @app.exception_handler(SQLAlchemyError) async def handle_database_error(request: Request, exc: SQLAlchemyError) -> JSONResponse: logger.exception( "database_error path=%s user_id=%s", request.url.path, request.headers.get("X-User-Id"), ) return JSONResponse( status_code=500, content={"code": "DATABASE_ERROR", "message": "database operation failed", "data": None}, ) @app.exception_handler(Exception) async def handle_unexpected_error(request: Request, exc: Exception) -> JSONResponse: logger.exception( "unexpected_error path=%s user_id=%s", request.url.path, request.headers.get("X-User-Id"), ) return JSONResponse( status_code=500, content={"code": "INTERNAL_ERROR", "message": "internal server error", "data": None}, )