66 lines
2.3 KiB
Python
66 lines
2.3 KiB
Python
from fastapi import Request, status
|
|
from fastapi.responses import JSONResponse
|
|
from fastapi.exceptions import RequestValidationError
|
|
from starlette.exceptions import HTTPException
|
|
from typing import Union, Dict, Any
|
|
|
|
from mooc.core.response import ResponseFactory
|
|
from mooc.core.logger import get_logger
|
|
|
|
logger = get_logger(__name__)
|
|
|
|
async def validation_exception_handler(request: Request, exc: RequestValidationError):
|
|
"""处理请求参数验证错误"""
|
|
logger.warning(f"Request validation error: {exc.errors()}")
|
|
|
|
# 格式化错误信息
|
|
error_details = []
|
|
for error in exc.errors():
|
|
error_details.append({
|
|
"loc": error.get("loc", []),
|
|
"msg": error.get("msg", ""),
|
|
"type": error.get("type", "")
|
|
})
|
|
|
|
return JSONResponse(
|
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
|
content=ResponseFactory.failed_validation(
|
|
msg="请求参数验证失败",
|
|
errors=error_details
|
|
)
|
|
)
|
|
|
|
async def http_exception_handler(request: Request, exc: HTTPException):
|
|
"""处理HTTP异常"""
|
|
logger.warning(f"HTTP exception: {exc.status_code} - {exc.detail}")
|
|
|
|
# 根据状态码选择适当的响应生成方法
|
|
if exc.status_code == status.HTTP_404_NOT_FOUND:
|
|
content = ResponseFactory.not_found(msg=str(exc.detail))
|
|
elif exc.status_code == status.HTTP_401_UNAUTHORIZED:
|
|
content = ResponseFactory.unauthorized(msg=str(exc.detail))
|
|
elif exc.status_code == status.HTTP_403_FORBIDDEN:
|
|
content = ResponseFactory.forbidden(msg=str(exc.detail))
|
|
else:
|
|
content = ResponseFactory.error(
|
|
code=exc.status_code,
|
|
msg=str(exc.detail)
|
|
)
|
|
|
|
return JSONResponse(
|
|
status_code=exc.status_code,
|
|
content=content,
|
|
headers=exc.headers or {}
|
|
)
|
|
|
|
async def generic_exception_handler(request: Request, exc: Exception):
|
|
"""处理所有其他未捕获的异常"""
|
|
logger.exception(f"Unhandled exception: {str(exc)}")
|
|
|
|
return JSONResponse(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
content=ResponseFactory.server_error(
|
|
msg="服务器内部错误",
|
|
data={"detail": str(exc)} if not isinstance(exc, AssertionError) else None
|
|
)
|
|
) |