Skip to content

13. FastAPI 请求对象Request ​

Request 提供原始请求上下文 ​

声明 request: Request,FastAPI 会注入本次请求对象。它适合读取请求头、客户端地址、原始正文、中间件写入的上下文;常规业务字段仍建议用明确的参数模型。

python
from json import JSONDecodeError
from fastapi import FastAPI, HTTPException, Request

app = FastAPI()

@app.get("/inspect/{item_id}")
async def inspect(item_id: int, request: Request):
    return {
        "method": request.method,
        "path": request.url.path,
        "item_id": request.path_params["item_id"],
        "tags": request.query_params.getlist("tag"),
        "user_agent": request.headers.get("user-agent"),
        "Authorization": request.headers.get("Authorization"),
        "cookies": request.cookies,
        "client_host": request.client.host if request.client else None,
        "has_session_cookie": "session" in request.cookies,
    }

@app.post("/raw-json")
async def raw_json(request: Request):
    try:
        data = await request.json()
    except (JSONDecodeError, UnicodeDecodeError):
        raise HTTPException(400, "正文不是合法 JSON")
    return {"received": data}

保存为 main.py 并运行 uv run uvicorn main:app --reload。访问 /inspect/12?tag=a&tag=b,观察重复参数通过 getlist 被完整读取;在 /raw-json 发送非法 JSON,应得到主动转换后的 400。

前端访问 ​

bash
GET HTTP://127.0.0.1:8000/inspect/18?tags=user,admin
Content-Type: application/json
Authorization: Bearer 123.456.7890
Cookie: session_id=123456

常用入口及代价 ​

入口返回内容注意点
request.headers请求头映射不记录令牌和 Cookie 原文
request.cookiesCookie 映射客户端提供,不能直接信任
await request.body()完整字节串大正文会占内存
await request.json()JSON 解析结果不自动做模型字段验证
request.stream()异步字节块适合大正文逐块处理
request.state本次请求附加属性可放 request_id、认证上下文
request.app.state应用实例资源常放共享 HTTP 客户端

使用 async for chunk in request.stream() 消费流后,通常不能再假设能重复调用 .body()、.json() 或 .form()。中间件随意读取正文也可能干扰下游,需要理解缓存与流的行为。

客户端 IP 与反向代理 ​

应用直连时 request.client 是对端;经过反向代理时可能是代理地址。X-Forwarded-For 来自请求头,只有在可信代理边界正确配置后才可用于真实 IP 判断。不能无条件相信外部客户端伪造的转发头。

原始正文常用于 Webhook 签名校验:应对原始字节做签名验证,然后解析 JSON,避免重新序列化改变字节顺序。若需要验证第三方签名,应严格按对应服务协议实现。

练习:添加中间件设置 request.state.request_id,在接口中读取;只返回允许公开的上下文字段,避免把整个请求头原样回显。