Files
fastapi/backend/app/core/errors.py
T

65 lines
2.3 KiB
Python
Raw Normal View History

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},
)