65 lines
2.3 KiB
Python
65 lines
2.3 KiB
Python
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 request_id=%s",
|
|
exc.code,
|
|
request.url.path,
|
|
request.headers.get("X-Request-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 request_id=%s errors=%s",
|
|
request.url.path,
|
|
request.headers.get("X-Request-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 request_id=%s",
|
|
request.url.path,
|
|
request.headers.get("X-Request-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 request_id=%s",
|
|
request.url.path,
|
|
request.headers.get("X-Request-Id"),
|
|
)
|
|
return JSONResponse(
|
|
status_code=500,
|
|
content={"code": "INTERNAL_ERROR", "message": "internal server error", "data": None},
|
|
)
|