FastAPI

fastapi2026-09-16 17:09:46

FastAPI 是一个使用 Python 类型注解定义 Web API 的 ASGI Web 框架。它将路由、数据校验、依赖注入和 OpenAPI 描述结合起来,适合构建需要明确数据契约的 HTTP 服务。

FastAPI 应用本身负责描述和处理 API;实际监听网络端口通常还需要 Uvicorn 等 ASGI 服务器。

路径操作

FastAPI 使用装饰器把 HTTP 方法和 URL 路径映射到 Python 函数:

from fastapi import FastAPI

app = FastAPI()

@app.get("/items/{item_id}")
async def read_item(item_id: str):
    return {"itemId": item_id}

@app.get()、@app.post()、@app.put() 和 @app.delete() 等装饰器定义路径操作。函数参数中的名称如果出现在路径模板中,会被识别为路径参数;普通标量参数通常会成为查询参数;Pydantic 模型参数通常会成为请求体。

路径操作既可以使用 async def,也可以使用普通 def。按照并发与 async/await 指南,调用需要 await 的异步网络、数据库或文件接口时使用 async def;同步阻塞代码不能仅因为放进异步函数就自动变成非阻塞代码。

请求体与数据校验

FastAPI 使用 Pydantic 模型声明请求体:

from pydantic import BaseModel, ConfigDict, Field

class SearchRequest(BaseModel):
    model_config = ConfigDict(extra="forbid")

    query: str = Field(min_length=1, max_length=4000)
    top_k: int = Field(default=4, ge=1, le=10)

当路径操作接收 SearchRequest 时,FastAPI 会读取 JSON、调用 Pydantic 完成转换和校验,并把模型的 JSON Schema 加入 OpenAPI。字段约束可以限制长度、数值范围和格式;extra="forbid" 可以拒绝契约之外的字段。

请求模型解决的是输入边界校验。业务规则、权限判断以及需要访问外部系统的校验,通常仍应放在服务层或依赖中。

依赖注入

FastAPI 的依赖注入系统可以复用身份验证、权限检查、连接获取和公共参数处理:

from typing import Annotated
from fastapi import Depends

async def require_user() -> UserContext:
    ...

@app.get("/profile")
async def profile(
    context: Annotated[UserContext, Depends(require_user)],
):
    return context

依赖本身可以继续声明子依赖。例如,管理员依赖可以先调用用户依赖,再检查用户的权限等级。依赖产生的参数和安全要求也能进入 OpenAPI 描述。

依赖注入适合表达“执行路径操作前必须获得什么”。应用工厂参数或 app.state 则更适合在测试中替换服务对象、保存应用级共享状态。两种方式可以配合使用,但请求身份等逐请求数据不应放进跨请求共享的全局状态。

中间件与请求上下文

HTTP 中间件会包裹每一次请求和响应:

from uuid import uuid4
from fastapi import Request

@app.middleware("http")
async def request_context(request: Request, call_next):
    request.state.request_id = str(uuid4())
    response = await call_next(request)
    response.headers["X-Request-ID"] = request.state.request_id
    return response

中间件适合生成请求 ID、记录耗时、设置统一响应头或执行跨接口策略。request.state 可以保存当前请求链路的数据;它不同于 app.state,不会用于跨请求共享状态。

如果配置了多个中间件,它们会形成调用栈:请求阶段由外向内执行,响应阶段按相反方向返回。

异常与响应

FastAPI 对请求校验失败提供默认处理,也允许通过 @app.exception_handler()覆盖框架异常或处理业务异常:

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

@app.exception_handler(RequestValidationError)
async def validation_error(
    request: Request,
    error: RequestValidationError,
):
    return JSONResponse(
        status_code=422,
        content={
            "code": "INVALID_INPUT",
            "requestId": request.state.request_id,
        },
    )

自定义异常处理可以统一状态码和错误结构,也可以避免把请求体、凭据或内部异常信息直接暴露给客户端。

路径操作直接返回字典或 Pydantic 模型时,FastAPI 会生成 JSON 响应。需要精确控制状态码、响应头或响应内容时,可以直接返回 JSONResponse 等 Response 对象。

OpenAPI 与接口文档

FastAPI 根据路径、参数、请求模型和依赖自动生成 OpenAPI Schema 与交互式文档。

常见默认入口是:

  • /openapi.json:OpenAPI Schema;
  • /docs:Swagger UI;
  • /redoc:ReDoc。

这些路径可以在创建应用时调整,也可以关闭某个文档界面。自动生成文档并不意味着 API 契约已经完整:返回类型、状态码和错误响应如果没有显式描述,生成的 OpenAPI 可能无法完整反映真实行为。

应用生命周期与共享资源

数据库连接池、HTTP 客户端、机器学习模型等应用级资源通常需要在启动时创建、在关闭时释放。FastAPI 当前推荐使用 lifespan 管理这类生命周期。

简单的惰性初始化也可以把资源保存在 app.state,但并发初始化、失败恢复和关闭清理需要由应用自行处理。多进程部署时,每个 Worker 都有独立内存;进程内的 app.state 不会自动跨 Worker 共享。

运行与测试

FastAPI 是 ASGI 应用,需要由 Uvicorn 等 ASGI 服务器运行。Uvicorn 可以加载一个应用对象,也可以使用工厂模式调用返回 FastAPI 实例的函数。开发环境的自动重载不应直接当作生产运行策略。

FastAPI 的 TestClient基于 HTTPX,可以在不启动真实网络服务器的情况下测试完整的请求处理流程:

from fastapi.testclient import TestClient

def test_live():
    with TestClient(create_app()) as client:
        response = client.get("/health/live")
        assert response.status_code == 200

应用工厂允许测试传入假的服务、认证器或存储,从而隔离外部系统。接口测试应覆盖正常响应、输入校验、身份权限、统一错误格式和就绪状态;TestClient 通过不等同于真实代理、网络和生产部署已经验收。

本页目录