FastAPI大全--HTTPException 的传递机制
·
FastApi大全-异常得传递流程
我们在之前已经构造了MVC架构目录–>《FastApi大全-优雅得构造MVC架构目录》
FastAPI 中 HTTPException 的传递机制:
我们在使用fastapi做接口或者微服务得时候,会遇到Service层的异常传递问题,下文我们说一下其中的HTTPException 传递原理。
HTTPException 传递机制
HTTPException 是一种常见的异常处理方式,用于在服务层(Service)和控制层(Controller)之间传递错误信息。其核心机制是通过抛出异常,由控制层捕获并转换为 HTTP 响应。
Service 层抛出 HTTPException
在 Service 层,可以通过抛出 HTTPException 来传递错误状态码和详细信息。HTTPException 通常包含状态码(如 400、404、500)和错误消息。例如:
from fastapi import HTTPException
def get_user(user_id: int):
if user_id <= 0:
raise HTTPException(status_code=400, detail="Invalid user ID")
# 其他业务逻辑
控制层捕获 HTTPException
控制层负责捕获 Service 层抛出的 HTTPException,并将其转换为对应的 HTTP 响应。在 FastAPI 或 Flask 等框架中,HTTPException 会自动被框架的异常处理器捕获并转换为响应。
from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.get("/users/{user_id}")
def read_user(user_id: int):
try:
user = get_user(user_id)
return user
except HTTPException as e:
raise e # FastAPI 会自动处理
自定义异常处理器
如果需要进一步定制异常处理逻辑,可以在控制层注册自定义异常处理器。例如,在 FastAPI 中可以通过 @app.exception_handler 实现:
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
app = FastAPI()
@app.exception_handler(HTTPException)
async def http_exception_handler(request: Request, exc: HTTPException):
return JSONResponse(
status_code=exc.status_code,
content={"message": exc.detail},
)
统一错误响应格式
为了保持 API 的一致性,可以在 Service 层和控制层之间约定统一的错误响应格式。例如:
raise HTTPException(
status_code=400,
detail={
"error": "InvalidInput",
"message": "User ID must be positive",
}
)
中间件处理
在某些框架中,可以通过中间件(Middleware)全局捕获和处理异常,避免在每个控制层方法中重复捕获逻辑。例如:
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
app = FastAPI()
@app.middleware("http")
async def catch_exceptions(request: Request, call_next):
try:
return await call_next(request)
except HTTPException as e:
return JSONResponse(
status_code=e.status_code,
content={"error": e.detail},
)
通过以上机制,Service 层可以高效地将错误信息传递到控制层,并由控制层统一转换为 HTTP 响应。
实例:
┌─────────────────────────────────────────────────────────────────────┐
│ 调用链 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ Controller 上传 │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ try: │ │
│ │ result = await service.batch_update_failed_data(...) │ │
│ │ return {"code": 200, ...} │ │
│ │ except HTTPException as e: ← 捕获 HTTPException │ │
│ │ return {"code": e.status_code, "message": e.detail} │ │
│ │ except Exception as e: │ │
│ │ return {"code": 500, ...} │ │
│ └──────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ Service: batch_update_failed_data 上传服务service │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ try: │ │
│ │ await self.insert_audit_md_shop(...) │ │
│ │ except HTTPException: ← ✅ 重新抛出 │ │
│ │ raise ← 传递给上层 │ │
│ │ except Exception as e: │ │
│ │ raise HTTPException(...) ← 转换为 HTTPException │ │
│ └──────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ Service: insert_audit_md_shop 插入到门店表service │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ if existing_shop: │ │
│ │ raise HTTPException( │ │
│ │ status_code=409, │ │
│ │ detail=f"门店ID '{t_shop_id}' 已绑定" │ │
│ │ ) │ │
│ └──────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
更多推荐
所有评论(0)