FastAPI实战技巧:深入剖析中间件、Session与Cookie的核心机制

FastAPI 是一个现代、高性能的 Python Web 框架,基于 Starlette 和 Pydantic,支持异步编程。它提供了灵活的中间件机制,以及对 Session 和 Cookie 的内置支持,非常适合构建高效的 API 和 Web 应用。本文将详细介绍 FastAPI 的中间件、Session 和 Cookie 的使用方法,并通过实例代码进行说明。

1. FastAPI 中间件简介

中间件(Middleware)是 FastAPI 中用于在请求和响应之间执行额外逻辑的机制。它可以处理诸如日志记录、身份验证、请求修改等功能。FastAPI 的中间件基于 Starlette,采用异步方式运行。

1.1 中间件的工作原理

中间件本质上是一个在请求到达路由处理函数之前和响应返回客户端之后执行的函数。它通过 call_next(request) 调用下一个中间件或路由处理器,并可以修改请求或响应。

1.2 创建自定义中间件

以下是一个简单的中间件示例,用于记录请求的处理时间。

python 复制代码
from fastapi import FastAPI, Request
import time

app = FastAPI()

# 自定义中间件
@app.middleware("http")
async def log_request_time(request: Request, call_next):
    start_time = time.time()
    response = await call_next(request)  # 调用下一个中间件或路由
    process_time = time.time() - start_time
    print(f"请求路径: {request.url.path}, 处理时间: {process_time:.4f} 秒")
    return response

@app.get("/")
async def root():
    return {"message": "Hello, FastAPI!"}

说明:

  • • @app.middleware("http") 装饰器定义了一个 HTTP 中间件。
  • • request: Request 是传入的请求对象。
  • • call_next 是异步函数,用于将请求传递给下一个处理环节。
  • • 中间件在控制台打印请求路径和处理时间。

运行后,访问 http://127.0.0.1:8000/,你会在终端看到类似以下输出:

makefile 复制代码
请求路径: /, 处理时间: 0.0012 秒

2. FastAPI 中的 Session

FastAPI 本身没有内置的 Session 管理,但可以通过第三方库(如 itsdangerous)或自定义实现来支持会话管理。Session 通常用于在多次请求之间存储用户状态。

以下是一个基于 Cookie 的简单 Session 实现:

python 复制代码
from fastapi import FastAPI, Request, Response
from fastapi.responses import JSONResponse
import uuid

app = FastAPI()

# 模拟会话存储(实际应用中可以用数据库)
session_data = {}

@app.get("/set-session")
async def set_session(response: Response):
    session_id = str(uuid.uuid4())  # 生成唯一会话 ID
    session_data[session_id] = {"user": "test_user", "login_time": time.time()}
    response.set_cookie(key="session_id", value=session_id, httponly=True)
    return {"message": "Session 已设置", "session_id": session_id}

@app.get("/get-session")
async def get_session(request: Request):
    session_id = request.cookies.get("session_id")
    if session_id and session_id in session_data:
        return {"session_data": session_data[session_id]}
    return {"message": "未找到会话"}

说明:

  • • /set-session 路由生成一个唯一的 session_id,存储在内存中的 session_data 字典,并通过 set_cookie 设置到客户端。
  • • /get-session 路由从请求中获取 Cookie 的 session_id,并返回对应的会话数据。
  • • httponly=True 确保 Cookie 只能通过 HTTP 访问,防止客户端脚本访问。

运行后:

    1. 访问 /set-session,浏览器会设置一个 session_id Cookie。
    1. 访问 /get-session,返回对应的会话信息。

Cookie 是客户端和服务器之间传递的小块数据,常用于身份验证、会话管理等。FastAPI 提供了简单的方法来设置和读取 Cookie。

通过 Response 对象的 set_cookie 方法可以设置 Cookie:

python 复制代码
from fastapi import FastAPI, Response

app = FastAPI()

@app.get("/set-cookie")
async def set_cookie(response: Response):
    response.set_cookie(key="user_id", value="12345", max_age=3600, httponly=True)
    return {"message": "Cookie 已设置"}

参数说明:

  • • key:Cookie 的名称。
  • • value:Cookie 的值。
  • • max_age:Cookie 的有效期(秒)。
  • • httponly:防止客户端脚本访问。

通过 Request 对象的 cookies 属性读取 Cookie:

python 复制代码
from fastapi import FastAPI, Request

app = FastAPI()

@app.get("/read-cookie")
async def read_cookie(request: Request):
    user_id = request.cookies.get("user_id")
    if user_id:
        return {"user_id": user_id}
    return {"message": "未找到 Cookie"}

运行后:

    1. 访问 /set-cookie,设置一个 user_id Cookie。
    1. 访问 /read-cookie,返回 {"user_id": "12345"}。

我们可以结合中间件检查 Cookie,实现简单的身份验证:

python 复制代码
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import JSONResponse

app = FastAPI()

@app.middleware("http")
async def check_cookie(request: Request, call_next):
    if request.url.path.startswith("/protected"):
        user_id = request.cookies.get("user_id")
        if not user_id:
            return JSONResponse(status_code=403, content={"message": "需要登录"})
    response = await call_next(request)
    return response

@app.get("/protected/data")
async def protected_data():
    return {"message": "这是受保护的数据"}

说明:

  • • 中间件检查请求路径是否以 /protected 开头,并验证是否存在 user_id Cookie。
  • • 如果没有 Cookie,返回 403 错误。

4. 综合实例:用户登录系统

以下是一个结合中间件、Session 和 Cookie 的完整示例,模拟用户登录系统:

python 复制代码
from fastapi import FastAPI, Request, Response, HTTPException
from fastapi.responses import JSONResponse
import uuid
import time

app = FastAPI()
session_data = {}

# 中间件:检查登录状态
@app.middleware("http")
async def auth_middleware(request: Request, call_next):
    if request.url.path.startswith("/api"):
        session_id = request.cookies.get("session_id")
        if not session_id or session_id not in session_data:
            return JSONResponse(status_code=401, content={"message": "未登录"})
    response = await call_next(request)
    return response

# 登录路由
@app.post("/login")
async def login(response: Response):
    session_id = str(uuid.uuid4())
    session_data[session_id] = {"user": "admin", "login_time": time.time()}
    response.set_cookie(key="session_id", value=session_id, httponly=True, max_age=3600)
    return {"message": "登录成功"}

# 受保护的 API
@app.get("/api/user")
async def get_user(request: Request):
    session_id = request.cookies.get("session_id")
    return {"user": session_data[session_id]["user"]}

# 退出登录
@app.post("/logout")
async def logout(request: Request, response: Response):
    session_id = request.cookies.get("session_id")
    if session_id in session_data:
        del session_data[session_id]
    response.delete_cookie("session_id")
    return {"message": "已退出登录"}

运行流程:

    1. 访问 /login,设置 session_id Cookie 并保存会话。
    1. 访问 /api/user,中间件验证 Cookie,返回用户信息。
    1. 访问 /logout,删除会话和 Cookie。

4. 总结

FastAPI 的中间件、Session 和 Cookie 提供了强大的工具来处理请求和用户状态:

  • • 中间件:适合全局逻辑,如日志、身份验证。
  • • Session:通过 Cookie 或数据库实现状态管理。
  • • Cookie:用于在客户端和服务器之间传递数据。
相关推荐
这里有鱼汤2 分钟前
10 分钟搞定一个 Python Web 应用?这不比泡面更香!🍜
python
梓羽玩Python7 分钟前
这个开源神器终结了AI数据整合的噩梦!一键聚合网页、代码、论文到剪贴板!
人工智能·python·github
谦行9 分钟前
前端视角 Java Web 入门手册 5.4:真实世界 Web 开发——Java Web 代码组织与分层
java·后端·架构
Goboy12 分钟前
构建异步消息通信机制设计与实现
后端·程序员·架构
一个天蝎座 白勺 程序猿16 分钟前
Python(16)Python文件操作终极指南:安全读写与高效处理实践
开发语言·python·安全
汪小成22 分钟前
NestJS学习笔记-02-模块、控制器与服务,手把手构建你的第一个CRUD API!🚀
后端·nestjs
天才测试猿26 分钟前
接口测试之postman使用指南
自动化测试·软件测试·python·测试工具·职场和发展·接口测试·postman
databook26 分钟前
Python3.14 即将带来的变化
python
小周不摆烂1 小时前
解锁元生代:ComfyUI工作流与云原生后端的深度融合
后端
qq_447663051 小时前
Spring-注解编程
java·后端·spring