FastAPI 请求和响应(深入浅出)

FastAPI 请求和响应:从入门到实战

在构建现代 Web 应用时,后端服务的核心任务之一就是处理来自客户端的请求,并返回合适的响应。FastAPI 作为近年来崛起的高性能 Python 框架,凭借其自动文档生成、类型提示支持和异步性能优势,成为众多开发者的首选。而理解 FastAPI 请求和响应 的机制,是掌握整个框架的基础。

想象一下,你的后端服务就像一家餐厅的厨房。用户(客户端)点餐,厨师(服务器)接收订单(请求),处理食材(业务逻辑),最后把做好的菜(响应)端上桌。FastAPI 就是那个高效、智能的厨房管理系统,它能自动识别你点的菜(参数),并快速做出符合标准的菜品(响应)。

接下来,我们将一步步拆解 FastAPI 是如何处理请求与响应的。


什么是请求和响应?

在 Web 开发中,请求(Request)是客户端向服务器发送的“动作”,比如用户点击登录按钮、提交表单、获取数据等。而 响应(Response)是服务器对请求的“回话”,比如返回登录成功、返回用户信息列表等。

FastAPI 使用标准的 HTTP 协议来处理这些通信。它通过路径操作(Path Operations)定义接口,每个接口都对应一个 HTTP 方法,如 GET、POST、PUT、DELETE 等。

例如,当你访问 http://localhost:8000/users 时,FastAPI 会根据路径和请求方法决定调用哪个函数,然后返回响应。


定义简单的请求处理函数

我们先从最简单的例子开始。假设我们要创建一个接口,返回“Hello, World”作为响应。

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    # 返回一个字典,FastAPI 会自动转换为 JSON 格式
    return {"message": "Hello, World"}

这段代码中:

  • FastAPI() 创建了一个应用实例,它就是整个服务器的入口。
  • @app.get("/") 是路径操作装饰器,表示当客户端发送 GET 请求到根路径时,调用下面这个函数。
  • read_root() 是处理函数,它返回一个 Python 字典。FastAPI 会自动将其序列化为 JSON 格式,作为 HTTP 响应体。

启动服务后,访问 http://localhost:8000,你就会看到:

{"message": "Hello, World"}

这就是一次完整的 FastAPI 请求和响应 流程。


接收路径参数:动态路径的处理

有时候,我们需要根据 URL 中的参数来处理请求。比如 /users/123,其中 123 是用户的 ID。

FastAPI 支持路径参数(Path Parameters),通过 {} 语法定义动态部分。

from fastapi import FastAPI

app = FastAPI()

@app.get("/users/{user_id}")
def read_user(user_id: int):
    # user_id 是整数类型,FastAPI 会自动验证并转换
    return {"user_id": user_id, "name": f"User {user_id}"}

关键点说明:

  • {user_id} 是路径参数,FastAPI 会将其提取出来。
  • user_id: int 是类型提示,FastAPI 会检查传入的值是否为整数。
  • 如果用户访问 /users/abc,FastAPI 会自动返回 422 错误(验证失败),并提示“value is not a valid integer”。

这种类型提示 + 自动校验的机制,是 FastAPI 的一大亮点,大幅减少了手动验证的代码。


处理查询参数:GET 请求中的附加信息

查询参数(Query Parameters)是附加在 URL 问号后面的参数,比如 /users?limit=10&offset=0

FastAPI 提供了 Query 类来接收这些参数。

from fastapi import FastAPI, Query

app = FastAPI()

@app.get("/users")
def get_users(
    limit: int = Query(10, ge=1, le=100),   # 默认值 10,最小 1,最大 100
    offset: int = Query(0, ge=0)             # 默认值 0,必须 >= 0
):
    # 返回一个模拟的数据列表
    data = [{"id": i, "name": f"User {i}"} for i in range(offset, offset + limit)]
    return {"data": data, "limit": limit, "offset": offset}

解释如下:

  • Query(10, ge=1, le=100) 表示 limit 参数默认为 10,且必须在 1 到 100 之间。
  • ge 是 "greater than or equal"(大于等于),le 是 "less than or equal"(小于等于)。
  • offset 默认为 0,且必须大于等于 0。

访问 http://localhost:8000/users?limit=5&offset=2,你会得到:

{
  "data": [
    {"id": 2, "name": "User 2"},
    {"id": 3, "name": "User 3"},
    {"id": 4, "name": "User 4"},
    {"id": 5, "name": "User 5"},
    {"id": 6, "name": "User 6"}
  ],
  "limit": 5,
  "offset": 2
}

这展示了 FastAPI 如何优雅地处理复杂查询条件,并自动验证。


POST 请求与请求体处理

GET 请求通常用于获取数据,而 POST 请求用于提交数据。例如,用户注册时提交表单。

FastAPI 使用 Body 来接收请求体(Request Body)。

from fastapi import FastAPI, Body
from pydantic import BaseModel

app = FastAPI()

class UserCreate(BaseModel):
    username: str
    email: str
    age: int

@app.post("/users")
def create_user(user: UserCreate = Body(...)):
    # user 是一个 UserCreate 实例,FastAPI 自动解析 JSON 并验证
    return {"message": f"User {user.username} created successfully", "user": user.dict()}

说明:

  • BaseModel 是 Pydantic 提供的模型基类,用于定义数据结构。
  • UserCreate 模型定义了 username(字符串)、email(字符串)、age(整数)三个字段。
  • Body(...) 表示这是一个必需的请求体,... 是 Python 的“空值占位符”,表示该参数不可缺省。
  • FastAPI 会自动将 JSON 请求体解析为 UserCreate 对象,并验证字段类型和约束。

示例请求(使用 curl):

curl -X POST http://localhost:8000/users \
     -H "Content-Type: application/json" \
     -d '{"username": "alice", "email": "alice@example.com", "age": 25}'

返回:

{
  "message": "User alice created successfully",
  "user": {
    "username": "alice",
    "email": "alice@example.com",
    "age": 25
  }
}

响应模型与状态码控制

FastAPI 不仅能返回普通字典,还能返回自定义模型,并控制 HTTP 状态码。

from fastapi import FastAPI, status
from pydantic import BaseModel

app = FastAPI()

class UserResponse(BaseModel):
    id: int
    username: str
    email: str

@app.get("/users/{user_id}", response_model=UserResponse, status_code=status.HTTP_200_OK)
def get_user(user_id: int):
    # 模拟数据库查询
    if user_id == 1:
        return UserResponse(id=1, username="admin", email="admin@example.com")
    else:
        # 如果用户不存在,返回 404
        return {"detail": "User not found"}, status.HTTP_404_NOT_FOUND

重点:

  • response_model=UserResponse 告诉 FastAPI 返回的 JSON 必须符合 UserResponse 模型。
  • status_code=status.HTTP_200_OK 显式设置状态码。
  • 当用户不存在时,返回字典和状态码,FastAPI 会正确处理。

这确保了接口的返回格式统一,便于前端解析。


总结:掌握 FastAPI 请求和响应的关键

通过上面的讲解,我们可以总结出 FastAPI 请求和响应 的核心优势:

  • 类型提示驱动:通过 : str, : int, : UserCreate 等类型注解,FastAPI 自动完成参数解析与验证。
  • 自动文档生成:访问 http://localhost:8000/docs,你会发现一份完整的交互式 API 文档,无需额外编写。
  • 灵活的参数支持:路径参数、查询参数、请求体、头部、Cookie 等都能轻松处理。
  • 强大的错误处理:类型不匹配、缺失参数等都会返回清晰的错误信息。

FastAPI 的设计哲学是“少写代码,多做正确的事”。当你掌握了 FastAPI 请求和响应 的机制,你就拥有了构建高性能、可维护后端服务的利器。

无论你是初学者还是中级开发者,从今天开始,不妨动手写一个属于自己的 API 接口,体验 FastAPI 的简洁与强大。记住,每一次请求与响应,都是你与用户之间的一次高效对话。