跳转至

FastAPI异常处理

在 FastAPI 中,异常处理(Exception Handling)是构建健壮和用户友好的 API 的关键部分。FastAPI 提供了灵活而强大的机制来处理异常,包括内置的 HTTP 异常、全局异常处理器、自定义异常等。以下是详细介绍 FastAPI 异常处理的方法和技巧。

1. 内置 HTTP 异常

FastAPI 提供了一些内置的 HTTP 异常,这些异常可以用于返回标准的 HTTP 错误响应。例如:

  • HTTPException: 通用的 HTTP 异常类。
  • RequestValidationError: 请求验证失败时的异常类。

使用 HTTPException:

from fastapi import FastAPI, HTTPException

app = FastAPI()

@app.get("/items/{item_id}")
async def read_item(item_id: int):
    if item_id > 10:
        raise HTTPException(status_code=404, detail="Item not found")
    return {"item_id": item_id}

在上述例子中,当 item_id 大于 10 时,API 将返回 404 错误,错误详情为 "Item not found"。

2. 全局异常处理器

可以通过 exception_handler 装饰器来注册全局异常处理器。全局异常处理器可以捕获特定类型的异常并返回自定义的响应。

自定义异常处理器:

from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import JSONResponse

app = FastAPI()

class UnicornException(Exception):
    def __init__(self, name: str):
        self.name = name

@app.exception_handler(UnicornException)
async def unicorn_exception_handler(request: Request, exc: UnicornException):
    return JSONResponse(
        status_code=418,
        content={"message": f"Oops! {exc.name} did something. We are out of tea."},
    )

@app.get("/unicorns/{name}")
async def read_unicorn(name: str):
    if name == "yolo":
        raise UnicornException(name=name)
    return {"unicorn_name": name}

在上述例子中,自定义的 UnicornException 被注册为全局异常处理器。当 UnicornException 被引发时,API 将返回 418 状态码和自定义的错误信息。

3. 请求验证异常处理

FastAPI 自动处理请求验证异常(如 RequestValidationError),并返回 422 状态码和详细的验证错误信息。不过,开发者也可以自定义处理这些异常。

自定义请求验证异常处理:

from fastapi import FastAPI, Request
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse

app = FastAPI()

@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
    return JSONResponse(
        status_code=400,
        content={"detail": exc.errors(), "body": exc.body},
    )

在上述例子中,请求验证失败时将返回 400 状态码,并包括详细的错误信息和请求体。

4. 捕获所有未处理的异常

可以通过 app.exception_handler 捕获所有未处理的异常,并返回自定义的响应。这样可以防止 API 返回未预期的错误信息。

捕获所有异常:

from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse

app = FastAPI()

@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc: Exception):
    return JSONResponse(
        status_code=500,
        content={"message": "Internal server error"},
    )

在上述例子中,任何未处理的异常都会返回 500 状态码和自定义的错误信息。

5. 依赖引发的异常处理

FastAPI 允许在依赖项中引发异常,并在路径操作中捕获和处理这些异常。依赖项的异常处理和路径操作的异常处理类似。

在依赖项中引发异常:

from fastapi import FastAPI, Depends, HTTPException

app = FastAPI()

async def verify_token(token: str):
    if token != "valid-token":
        raise HTTPException(status_code=401, detail="Invalid token")
    return token

@app.get("/protected-route")
async def protected_route(token: str = Depends(verify_token)):
    return {"message": "Access granted"}

在上述例子中,如果提供的 token 无效,将引发 401 错误。

6. 使用自定义响应模型

FastAPI 允许使用 Pydantic 模型来定义异常响应的结构,从而提供一致且可预见的错误响应格式。

自定义响应模型:

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

app = FastAPI()

class ErrorResponse(BaseModel):
    detail: str

@app.exception_handler(HTTPException)
async def custom_http_exception_handler(request, exc: HTTPException):
    return JSONResponse(
        status_code=exc.status_code,
        content={"detail": exc.detail},
    )

@app.get("/items/{item_id}", response_model=ErrorResponse)
async def read_item(item_id: int):
    if item_id > 10:
        raise HTTPException(status_code=404, detail="Item not found")
    return {"item_id": item_id}

在上述例子中,ErrorResponse 模型定义了错误响应的结构。所有引发 HTTPException 的地方都会返回一致的错误响应格式。

7. 总结

FastAPI 提供了多种方式来处理异常,包括使用内置的 HTTP 异常、注册全局异常处理器、自定义请求验证异常处理器和捕获所有未处理的异常。通过灵活的异常处理机制,开发者可以构建健壮且用户友好的 API 服务。

评论