add
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
"""统一响应与业务异常(对齐《03-接口文档》1.2 统一响应结构)"""
|
||||
import uuid
|
||||
from contextvars import ContextVar
|
||||
from typing import Any
|
||||
|
||||
from fastapi import FastAPI, Request
|
||||
from fastapi.exceptions import RequestValidationError
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
from app.core import errors
|
||||
|
||||
# 请求链路 ID(中间件写入,日志/响应共用)
|
||||
request_id_ctx: ContextVar[str] = ContextVar("request_id", default="")
|
||||
|
||||
|
||||
def ok(data: Any = None, message: str = "ok") -> dict:
|
||||
return {
|
||||
"code": errors.OK,
|
||||
"message": message,
|
||||
"data": data if data is not None else {},
|
||||
"request_id": request_id_ctx.get() or str(uuid.uuid4()),
|
||||
}
|
||||
|
||||
|
||||
class BizException(Exception):
|
||||
"""业务异常:抛出后由全局处理器转为统一响应"""
|
||||
|
||||
def __init__(self, code: int, message: str | None = None, http_status: int = 200, data: dict | None = None):
|
||||
self.code = code
|
||||
self.message = message or errors.DEFAULT_MESSAGES.get(code, "error")
|
||||
self.http_status = http_status
|
||||
self.data = data or {}
|
||||
|
||||
|
||||
def _fail_body(code: int, message: str, data: dict | None = None) -> dict:
|
||||
return {
|
||||
"code": code,
|
||||
"message": message,
|
||||
"data": data or {},
|
||||
"request_id": request_id_ctx.get() or str(uuid.uuid4()),
|
||||
}
|
||||
|
||||
|
||||
def register_exception_handlers(app: FastAPI) -> None:
|
||||
@app.exception_handler(BizException)
|
||||
async def biz_handler(request: Request, exc: BizException) -> JSONResponse:
|
||||
return JSONResponse(status_code=exc.http_status, content=_fail_body(exc.code, exc.message, exc.data))
|
||||
|
||||
@app.exception_handler(RequestValidationError)
|
||||
async def validation_handler(request: Request, exc: RequestValidationError) -> JSONResponse:
|
||||
return JSONResponse(
|
||||
status_code=200,
|
||||
content=_fail_body(errors.PARAM_ERROR, f"参数错误: {exc.errors()[0].get('msg', '')}"),
|
||||
)
|
||||
|
||||
@app.exception_handler(Exception)
|
||||
async def unhandled_handler(request: Request, exc: Exception) -> JSONResponse:
|
||||
return JSONResponse(status_code=500, content=_fail_body(errors.INTERNAL_ERROR, "服务器内部错误"))
|
||||
Reference in New Issue
Block a user