今日目标:普通框架写出的代码往往是一坨”意大利面条”,所有逻辑纠缠在一起。今天我们要学习 FastAPI 的独门绝技 —— 依赖注入 (Depends),学会如何像搭积木一样复用逻辑(如鉴权、数据库连接);同时掌握 Middleware,实现全局层面的流量拦截。今天不只是写代码,而是要彻底理解 “依赖注入如何解耦代码”、“中间件和依赖的区别” 以及 “如何设计可复用的依赖函数”。
学习内容 (30 mins)
在开始写代码前,先搞懂这些核心概念,否则后面的代码你会看得云里雾里。依赖注入 (Dependency Injection) (15 mins)
依赖注入 (Dependency Injection) (15 mins)
什么是依赖注入?依赖注入是一种设计模式,将依赖关系从代码内部移到外部,通过参数传递的方式提供依赖。为什么需要依赖注入?依赖注入方式:Depends 的工作原理:
- 代码复用:将通用逻辑(如鉴权、数据库连接)封装成函数,多个接口复用
- 解耦代码:业务逻辑和横切关注点(cross-cutting concerns)分离
- 易于测试:可以轻松替换依赖,便于单元测试
- 自动执行:FastAPI 自动执行依赖函数,无需手动调用
- FastAPI 发现路由函数有
Depends(verify_token) - 在执行路由函数前,先执行
verify_token函数 - 如果
verify_token抛出异常,路由函数不会执行,直接返回错误 - 如果
verify_token成功,将返回值传递给路由函数(如果需要)
中间件 (Middleware) (15 mins)
中间件 (Middleware) (15 mins)
什么是中间件?中间件是在请求处理前后执行的函数,可以拦截所有请求和响应。为什么需要中间件?
- 全局处理:对所有请求执行相同的操作(如日志记录、CORS 处理)
- 请求拦截:在请求到达路由前进行处理
- 响应修改:在响应返回前添加头部、修改内容
- 依赖注入 (Depends):
- 作用于特定的路由函数
- 适合业务强相关的逻辑(如:用户必须登录)
- 可以传递返回值给路由函数
- 中间件 (Middleware):
- 作用于全局所有请求
- 适合通用的横切关注点(如:记录请求耗时、CORS 处理)
- 不能直接传递数据给路由函数
- 中间件:小区保安(谁进小区都得看一眼)
- 依赖注入:门禁卡(只有进自家单元门才刷卡)
- 请求进入 → 中间件 1 → 中间件 2 → … → 路由函数
- 路由函数执行
- 响应返回 → 中间件 2 → 中间件 1 → 客户端
- CORS:处理跨域请求
- 日志记录:记录每个请求的 URL、方法、耗时
- 请求验证:验证请求格式、大小限制
- 响应压缩:压缩响应内容
代码任务 (90 mins)
任务 A:编写通用鉴权依赖
创建一个可复用的鉴权依赖函数。任务分解:代码解释:
- 创建依赖函数,从 Header 中读取 Token
- 验证 Token 是否有效
- 如果无效,抛出异常
Header(...):从 HTTP Header 中获取参数HTTPException:抛出 HTTP 异常,FastAPI 自动转换为错误响应- 依赖链:
get_current_user可以依赖verify_token,形成依赖链
- 检查文件语法是否正确
- 尝试导入:
python -c "from 17_deps import verify_token; print('OK')"
任务 B:编写耗时统计中间件
创建一个中间件,统计每个请求的处理时间。代码解释:验证步骤:
CORSMiddleware:处理跨域请求,前端开发必需@app.middleware("http"):定义 HTTP 中间件call_next(request):调用下一个处理环节(路由函数)dependencies=[Depends(...)]:在路由级别使用依赖current_user: dict = Depends(...):接收依赖函数的返回值
- 测试中间件:
- 访问
http://localhost:8000/ - 打开浏览器开发者工具 (F12) -> Network
- 点击请求 -> 查看 Response Headers
- 应该能看到
x-process-time: 0.000xxxx
- 访问
- 测试依赖注入:
- 直接访问
http://localhost:8000/items/-> 会报错 (Missing Header) - 打开 Swagger UI (
/docs) - 点击
/items/-> Try it out - 在 Header 参数栏输入
x-token: fake-secret - 执行 -> 成功拿到数据
- 直接访问
- 测试依赖返回值:
- 访问
http://localhost:8000/me - 在 Header 中添加
x-token: fake-secret - 应该能看到用户信息
- 访问
拓展任务 (30 mins)
挑战 1:数据库连接依赖
任务:创建一个数据库连接依赖,自动为每个请求提供数据库会话。提示:
挑战 2:请求日志中间件
任务:创建一个中间件,记录每个请求的 URL、方法、IP 地址和处理时间。提示:使用
request.client.host 获取客户端 IP,使用 request.url 获取 URL。今日产出物
17_deps.py- 依赖函数定义17_main.py- 使用依赖注入和中间件的 FastAPI 应用
参考代码
查看参考代码
在 GitHub 查看完整的示例代码
在线运行
使用在线编辑器测试代码
实际应用场景
依赖注入在 API 开发中的应用
- 鉴权验证:统一的 Token 验证逻辑,多个接口复用
- 数据库连接:自动为每个请求提供数据库会话
- 权限检查:根据用户角色检查是否有权限访问
- 数据获取:从数据库或缓存中获取用户信息
- 配置读取:统一读取配置信息
中间件在 API 开发中的应用
- CORS 处理:处理跨域请求,前端开发必需
- 请求日志:记录每个请求的详细信息
- 性能监控:统计请求处理时间,定位性能瓶颈
- 请求限流:限制请求频率,防止滥用
- 错误处理:统一处理异常,返回友好的错误信息
上一天: 数据验证
Day 16 | Pydantic 数据验证
下一天: 数据库整合
Day 18 | SQLAlchemy 数据库整合