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:用于在客户端和服务器之间传递数据。
相关推荐
北执南念1 分钟前
如何在 Spring Boot 中设计和返回树形结构的组织和部门信息
java·spring boot·后端
修仙的人9 分钟前
【开发环境】 VSCode 快速搭建 Python 项目开发环境
前端·后端·python
FinalLi11 分钟前
SpringBoot3.5.0项目使用ALLATORI JAVA混淆器
后端
hhhh明21 分钟前
Windows11 运行IsaacSim GPU Vulkan崩溃
vscode·python
在钱塘江22 分钟前
LangGraph构建Ai智能体-12-高级RAG之自适应RAG
人工智能·python
站大爷IP29 分钟前
Python列表基础操作全解析:从创建到灵活应用
python
在钱塘江40 分钟前
LangGraph构建Ai智能体-12-高级RAG之纠错式RAG
人工智能·python
朦胧的心一样不平凡42 分钟前
robot framework
python
站大爷IP1 小时前
Python变量与基础数据类型:整型、浮点型和字符串操作全解析
python