惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

K
Kaspersky official blog
罗磊的独立博客
F
Fortinet All Blogs
人人都是产品经理
人人都是产品经理
量子位
V
Visual Studio Blog
Blog — PlanetScale
Blog — PlanetScale
M
MIT News - Artificial intelligence
B
Blog RSS Feed
腾讯CDC
博客园_首页
aimingoo的专栏
aimingoo的专栏
博客园 - 三生石上(FineUI控件)
博客园 - Franky
S
SegmentFault 最新的问题
N
Netflix TechBlog - Medium
小众软件
小众软件
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
L
LINUX DO - 热门话题
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Martin Fowler
Martin Fowler
D
Docker
P
Privacy & Cybersecurity Law Blog
S
Securelist
V
V2EX
Jina AI
Jina AI
阮一峰的网络日志
阮一峰的网络日志
T
Tor Project blog
The Hacker News
The Hacker News
Microsoft Azure Blog
Microsoft Azure Blog
AWS News Blog
AWS News Blog
The GitHub Blog
The GitHub Blog
有赞技术团队
有赞技术团队
T
The Exploit Database - CXSecurity.com
Help Net Security
Help Net Security
酷 壳 – CoolShell
酷 壳 – CoolShell
Application and Cybersecurity Blog
Application and Cybersecurity Blog
博客园 - 叶小钗
Recent Announcements
Recent Announcements
Cloudbric
Cloudbric
Y
Y Combinator Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Latest news
Latest news
MongoDB | Blog
MongoDB | Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Recorded Future
Recorded Future
V2EX - 技术
V2EX - 技术

博客园 - 一名程序媛呀

Anki插件开发必知必会:钩子函数与右键菜单定制 httpx 传参总报错?这次把 GET、POST、文件上传到响应处理的坑给你一次填平 从卡顿到丝滑:FastAPI 调用外部 API 的正确姿势(httpx 实战) 还在 XHR、Fetch 和 Axios 之间纠结?我踩过的坑,希望你一个都不用碰到 你的REST接口还在“过度投喂”数据吗?——FastAPI + GraphQL实战避坑指南 Uvicorn、Gunicorn 傻傻分不清?FastAPI 生产部署避坑指南 Termux里的二进制和脚本,到底怎么运行才不踩坑?Termux-service 保活妙招! 刚部署的 LibreTranslate 频频翻车?我掏出了 20 年前的 StarDict 词典,用 FastAPI 搭了个本地词典翻译 API 别再用网页翻译看源码了!你的私人翻译神器LibreTranslate,部署避坑指南来了 掏出手机就能搭个 WebDAV 同步服务器?这操作有点香 别只盯着GitBook了!这个文档神器让你的笔记秒变网站 写爬虫时用了代理还被封?Python 代理的那些隐藏坑,我替你踩明白了 FastAPI 身份验证总踩坑?这份 FastAPI Users “避坑指南”请收好 旧手机别扔!用 Termux 搭个私人云盘,比网盘香多了 你的FastAPI又在服务器上“跑不起来”了?来,今天咱把打包这件事彻底聊透 写页面时别再把 Element Plus 整个搬进来啦!Vue3按需加载的坑我帮你踩平了 前端包管理咋选?我从npm叛逃到pnpm的血泪史(附避坑指南) 聊聊 fetch 使用中我踩过的那些坑和正确打开方式 FastApiAdmin 后端接口开发好了,前端管理界面怎么调用与显示? 给 FastApiAdmin 加个“会议纪要”模块,我把后端二次开发的坑踩了个遍 我用了FastApiAdmin后,连夜把踩过的坑都整理出来了 告别 Typora 后的新欢:我把所有笔记迁移到了 Obsidian 这个“第二大脑” 你的Agent API还在裸奔?从认证到沙箱,我用FastAPI搭了几道防线 让 FastAPI Agent 思考不阻塞:手把手教你实现异步任务与后台处理方案 让FastAPI Agent真正记住你:聊聊会话记忆与持久化存储的落地实践 FastAPI Agent 函数调用实战:我让 AI 学会了“自己动手查天气“ 初探:用 FastAPI 搭建你的第一个 AI Agent 接口 FastAPI 少有人提的实用技巧:把 Depends 依赖提到路由层,代码少写60% FastAPI 生产环境静态文件完全指南:从 /favicon.ico 404 到 HSTS 混合内容,一次全根治 用了loguru我才明白,Python日志还能这么写 FastAPI 后台任务:BackgroundTasks 的使用场景与注意事项 FastAPI配置管理避坑指南:从硬编码到 .env 与 pydantic_settings 类,连路由用法都给你捋清楚 FastAPI 文件上传避坑全指南:分块存盘、类型校验与安全兜底 FastAPI + Pydantic 模型终极实战手册:从能跑就行到固若金汤,这些技巧你一定用得上 FastAPI + SQLAlchemy 2.0 通用CRUD操作手册 —— 从同步到异步,一次讲透 FastAPI订单防超卖实战:从数据库锁到Saga分布式事务,这一篇给你理清了 FastAPI 生产环境避坑指南:用 Alembic 管理数据库迁移,别再手动改表结构了! FastAPI服务半夜又挂了?先别急着重启,查查你的数据库连接池“池子”是不是漏了 FastAPI数据库ORM怎么选?我肝了三个Demo后,终于不再纠结了 Vue 3 组件通信,别只会用 Props 和 Emits 了,这几个狠活儿你得看看 Vue 3 组合式 API 香是香,但从Vue2迁移时你可别像我当初一样踩进这 3 个深坑里 我用fastapi-scaff搭了个项目,两天工期缩到两小时,老板以为我开挂了 FastAPI+Vue:文件分片上传+秒传+断点续传,这坑我帮你踩平了! FastAPI自动生成的API文档太丑?我花了一晚上把它改成了客户愿意付费的样子 告别手写 API 胶水代码:FastAPI 与 Vue 的“契约自动机” OpenAPI 实战 FastAPI + Vue 前后端分离实战:我的项目结构“避坑指南” FastAPI + Celery 实战:异步任务里调用 Redis 和数据库的全解析,及生产级组织方案 FastAPI里玩转Redis和数据库的正确姿势,别让异步任务把你坑哭了! FastAPI + Celery 实战:异步任务的坑与解法,我帮你踩了一遍 FastAPI子应用挂载:别再让root_path坑你一夜 FastAPI项目半夜报警吵醒你?聊聊告警这事儿怎么搞! 别再数据线了!用FastAPI 5分钟搭个局域网文件+剪贴板神器 FastAPI单元测试实战:别等上线被喷才后悔,TestClient用对了真香! FastAPI实战:WebSocket vs Socket.IO,这回真给我整明白了! 从0到1,FastAPI + PostgreSQL + Tortoise ORM 实战避坑指南 FastAPI + PostgreSQL 实战:给应用装上“缓存”和“日志”翅膀 FastAPI + PostgreSQL 实战:从入门到不踩坑,一次讲透
FastAPI状态共享秘籍:别再让中间件、依赖和路由“各自为政”了!
一名程序媛呀 · 2026-03-24 · via 博客园 - 一名程序媛呀

你是不是也遇到过这种场景:在中间件里好不容易解析出了用户ID,到了路由处理函数里,却还得再查一遍数据库?或者依赖项里计算好的权限信息,想传递给后续业务逻辑,只能吭哧吭哧用全局变量?

🎯 今天咱们就聊聊FastAPI里那个低调却强大的 Request.state 存储机制。我用一个真实的“用户画像”案例,带你走一遍从踩坑到优雅解决的全过程。保证你看完,就能让中间件、依赖和路由处理程序之间“手拉手”愉快地共享数据!

📌 本文将带你搞懂:

- 为什么全局变量是“毒药”?

- Request.state 的正确打开方式

- 一个完整的实战:在中间件中注入用户信息,通过依赖传递,最后在路由中使用。

- 避坑指南:State的生命周期、并发安全性,以及和Contextvar的恩怨情仇。

🍜 故事从一碗牛肉面说起

想象一下,你开了一家牛肉面馆。每个客人进来,你都得先问“要辣吗?”“要香菜吗?”。这个收集信息的过程,就像是 中间件。然后后厨根据这些信息,决定放多少辣、加不加香菜,这就像 依赖项。最后,一碗定制化的面端到客人面前,这就是 路由处理程序

如果你把“加辣”、“加香菜”这些信息写在收银台的一张公共小黑板上(全局变量),那当两个客人同时点餐时,后厨肯定会看花眼,把A客人的辣面端给B客人。这就是并发下的数据混乱!

FastAPI 的 Request.state 就相当于给每个客人发了一张专属的“点餐小票”,从收银台到后厨,这张小票全程跟着这碗面,绝对不会搞混。

🚀 实战:给每个请求贴上“用户画像”

好,不废话了,咱们直接上代码。假设我们有一个场景:需要从请求头中获取用户令牌,解析出用户信息,然后在后续的所有逻辑中都能用到这个用户信息。

1️⃣ 最傻最暴力的错误示范

# 全局变量,并发地狱的入口
current_user = None

@app.middleware("http")
async def add_user_middleware(request, call_next):
    global current_user
    token = request.headers.get("Authorization")
    # 模拟解析用户
    current_user = {"id": 1, "name": "张三"}
    response = await call_next(request)
    return response

@app.get("/profile")
async def get_profile():
    # 直接读取全局变量,多个请求会相互覆盖!!!
    return current_user

这里千万别学这种偷懒写的代码,否则半夜收到报警短信,说用户A看到了用户B的隐私信息,那就只能等着哭了。😭 全局变量在并发请求下就是个定时炸弹。

2️⃣ 优雅的救世主:Request.state

接下来重点来了!FastAPI 的 request.state 才是我们想要的“点餐小票”。它依附于每一个独立的请求对象,天然就是线程/协程安全的。

from fastapi import FastAPI, Request, Depends
from pydantic import BaseModel

app = FastAPI()

# 1. 中间件:负责把用户信息“贴”到 state 上
@app.middleware("http")
async def add_user_middleware(request: Request, call_next):
    # 假设从请求头获取token
    token = request.headers.get("Authorization")
    user_info = {"id": 1, "name": "李四", "role": "admin"}
    
    # 关键操作:把数据挂在 request.state 上
    request.state.user = user_info
    
    response = await call_next(request)
    return response

# 2. 依赖项:负责从 state 中取出数据,并注入给路由
async def get_current_user(request: Request):
    # 从 state 中获取之前挂载的数据
    user = request.state.user
    # 可以在这里做一些校验、权限判断
    if not user:
        # 也可以抛出异常
        return None
    return user

# 3. 路由处理程序:通过依赖项获取数据,清爽无比
@app.get("/profile")
async def get_profile(user: dict = Depends(get_current_user)):
    # 直接使用,再也不用担心数据乱串
    return {"msg": f"Hello, {user['name']}", "user": user}

看到没?整个流程清晰得像流水线:中间件负责写 request.state.user,依赖项负责读并注入,路由函数只管用。每个请求的state都是独立的,再也不用担心并发问题。

💡 再说个容易翻车的点

你可能会问:“那我把所有数据都塞进 request.state 里不就行了?” 别,这里有个性能陷阱

request.state 本质上是一个简单的对象,它适合存储元数据,比如用户ID、权限标识、请求开始时间等。如果你往里塞一个几MB的图片数据,或者一个包含上百个字段的复杂对象,那内存占用和GC压力会直线上升。我个人习惯是:state里只存“钥匙”,比如用户ID,真正的用户大数据,比如详细资料、权限树,还是在依赖项里用ID去缓存里拿,这样更稳。

🧠 进阶思考:State和Contextvar是啥关系?

如果你接触过Python的异步编程,可能会想到 contextvars。它也能在异步上下文中传递数据。那什么时候用 request.state,什么时候用 contextvars

我的理解是:request.state 是FastAPI框架层提供的,和Request生命周期绑定,在中间件、依赖、路由之间传递数据是它的本职工作,用起来最直接。而 contextvars 更底层,适合在跨函数、跨模块的复杂异步调用链中传递上下文(比如分布式追踪的trace_id)。但要注意,千万不要混用导致数据混乱。我自己写业务代码时,99%的情况用 request.state 就够了,简单又可靠。

📝 总结

好啦,今天这顿饭咱们就吃到这儿。简单回顾一下:

✅ 告别全局变量,拥抱 request.state 做请求级别的数据存储。

✅ 中间件负责写,依赖项负责读和注入,路由负责使用,各司其职。

✅ 警惕state里存大对象,只存“钥匙”才是优雅之道。

✅ 理解 request.state 和 contextvars 的区别,选对工具。

最后啰嗦一句,技术这东西,光看是记不住的,一定要自己敲一遍。赶紧打开你的编辑器,把上面那个用户画像的例子跑起来,然后换成你自己的业务逻辑试试。

如果你觉得这篇文章对你有帮助,或者你也踩过类似的坑,欢迎点个❤️收藏,或者分享给正在被FastAPI折磨的小伙伴。咱们下期再见,继续聊技术,聊生活~