我们在之前已经构造了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}' 已绑定"                │  │
│  │     )                                                        │  │
│  └──────────────────────────────────────────────────────────────┘  │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐