ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

FastAPI 全局依赖(Global Dependencies):为整个应用统一施加校验与预处理

FastAPI 全局依赖(Global Dependencies):为整个应用统一施加校验与预处理 FastAPI 全局依赖Global Dependencies为整个应用统一施加校验与预处理【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi本指南围绕 FastAPI 官方教程中的Global Dependencies章节展开讲解如何把依赖从单个路径操作path operation提升到整个应用级别让应用内每一个路由在进入处理函数之前都统一执行身份令牌、API Key 校验等逻辑。读完本文你将掌握FastAPI(dependencies[...])的完整用法、其与路径操作装饰器级依赖的差异以及它在子路由、依赖覆盖测试等场景中的实际行为并能直接对照本仓库的示例代码与测试用例进行验证。什么时候需要应用级的依赖在某些类型的应用中你会希望对整个应用而不是单个路由统一添加依赖。典型场景包括全站都需要校验的访问令牌如X-Token请求头全站都需要校验的 API Key如X-Key请求头需要在每次请求开始前统一执行的日志、鉴权、限流等横切逻辑。这与在路径操作装饰器中添加dependencies的做法非常相似区别只在于作用范围前者仅对当前这一个路由生效而后者会作用于应用内所有的路径操作。你同样可以把它们加到FastAPI应用上这就是全局依赖。快速上手把依赖传入FastAPI()构造函数全局依赖的声明方式极其简单在创建FastAPI()实例时通过dependencies参数传入一个由Depends()组成的列表即可。以下示例取自本仓库的官方示例源码 docs_src/dependencies/tutorial012_an_py310.pyfrom typing import Annotated from fastapi import Depends, FastAPI, Header, HTTPException async def verify_token(x_token: Annotated[str, Header()]): if x_token ! fake-super-secret-token: raise HTTPException(status_code400, detailX-Token header invalid) async def verify_key(x_key: Annotated[str, Header()]): if x_key ! fake-super-secret-key: raise HTTPException(status_code400, detailX-Key header invalid) return x_key app FastAPI(dependencies[Depends(verify_token), Depends(verify_key)]) app.get(/items/) async def read_items(): return [{item: Portal Gun}, {item: Plumbus}] app.get(/users/) async def read_users(): return [{username: Rick}, {username: Morty}]请注意加粗高亮的一行app FastAPI(dependencies[Depends(verify_token), Depends(verify_key)])两个依赖被声明在应用创建阶段。这样一来/items/、/users/以及此后新增的每一个路由都会在进入各自的路径操作函数前先执行verify_token与verify_key。这段代码的请求校验语义是每个请求都必须携带X-Token请求头且其值必须等于fake-super-secret-token否则抛出HTTPException(400)响应体为{detail: X-Token header invalid}每个请求还必须携带X-Key请求头且值必须等于fake-super-secret-key否则抛出HTTPException(400)响应体为{detail: X-Key header invalid}若校验通过依赖会继续向后续依赖链返回结果verify_key返回了x_key但应用级依赖的返回值不会传入路径操作函数——路径函数无需、也无法接收它。提示X-Token、X-Key是教程中虚构的自定义请求头。在真实项目中做安全校验时通常使用 FastAPI 内置的 Security 工具OAuth2、JWT、API Key 等收益更大本节内容更适合理解应用级横切逻辑这一通用机制。验证行为缺失或错误的请求头会得到什么响应本仓库针对该示例提供了完整的端到端测试 tests/test_tutorial/test_dependencies/test_tutorial012.py可以直接佐证上述行为。例如测试中先访问了不带请求头的接口确认两个路由都会被拦截response client.get(/items/) # 或 client.get(/users/) assert response.status_code 400 assert response.json() {detail: X-Token header invalid}当X-Token正确但X-Key错误时response client.get( /items/, headers{X-Token: fake-super-secret-token, X-Key: invalid}, ) assert response.status_code 400 assert response.json() {detail: X-Key header invalid}只有当两者都正确时请求才会进入路径操作并正常返回数据response client.get( /items/, headers{ X-Token: fake-super-secret-token, X-Key: fake-super-secret-key, }, ) assert response.status_code 200 assert response.json() [{item: Portal Gun}, {item: Plumbus}]该测试文件还对 OpenAPI Schema 做了断言因为依赖声明了Header()参数/items/与/users/两个接口在交互式文档/docs中都会把X-Token标注为必填请求头。这正是全局依赖与每个路由单独声明表现一致的地方——所有接口的文档都会被更新。运行验证方式上述逻辑通过 FastAPI 官方测试工具完成仓库内实际命令可参考 scripts/test.sh 中约定的测试运行方式也可以直接在项目根目录使用你的测试运行器执行tests/test_tutorial/test_dependencies/test_tutorial012.py。全局依赖与路径操作装饰器依赖的关系全局依赖并不是一套全新的机制它复用了路径操作装饰器级依赖的全部思想只是把作用域从单个路由扩展到整个应用。可对照的按路由声明版本见 docs_src/dependencies/tutorial006_an_py310.py其差异仅为依赖挂在单个路由上app.get(/items/, dependencies[Depends(verify_token), Depends(verify_key)]) async def read_items(): return [{item: Foo}, {item: Bar}]两处声明依赖的共同点在于执行方式相同都会被当成普通依赖解析与执行返回值均不使用在装饰器的dependencies里声明的依赖即使返回了值也不会传给路径操作函数。正因如此声明在全局或装饰器里的依赖不需要也不应该被声明为路径函数参数从而避免编辑器报未使用参数也让新读者不至于误删看似多余的参数。其区别如下表所示对比维度路径操作装饰器依赖应用级全局依赖声明位置app.get(/items/, dependencies[...])app FastAPI(dependencies[...])作用范围仅当前这一个路径操作应用中所有路径操作是否作用于之后 include 的子路由否是返回值是否传入路径函数否否能否声明请求需求Header 等能能能否抛出异常中断请求能能关于该章节中关于路径操作装饰器依赖的全部要点在此同样适用具体可展开为以下三类能力与教程 dependencies-in-path-operation-decorators.md 中描述一致依赖可以声明自身的请求需求或子依赖如示例中的verify_token(x_token: Annotated[str, Header()])FastAPI 会先从请求头解析出x_token再执行函数体依赖可以抛出异常校验失败时raise HTTPException(status_code400, ...)会立即中断请求并返回错误响应后续代码不会执行依赖可以返回值也可以不返回返回值只是给依赖链中的下游使用例如本例verify_key返回x_key对于应用级声明该值最终不会被用于任何路径操作但依赖本身一定会被执行。因此你完全可以把一个已经在别处复用的普通依赖返回值的那个同时挂到应用级即便它的返回值用不到校验逻辑依然会被执行。源码视角全局依赖是如何生效的从源码结构看全局依赖的实现路径非常清晰。在 fastapi/applications.py 中FastAPI.__init__接收可选的dependencies参数其类型标注为Sequence[Depends] | None官方文档字符串明确写道A list of global dependencies, they will be applied to eachpath operation, including in sub-routers.全局依赖列表会被应用到每一个路径操作包括子路由中。接着FastAPI 在初始化时会创建内部路由self.router并把该参数原样传递给APIRouter见 fastapi/applications.pyself.router: routing.APIRouter routing.APIRouter( routesroutes, redirect_slashesredirect_slashes, dependency_overrides_providerself, ... dependenciesdependencies, )也就是说所有通过app.get()、app.post()等装饰器注册到self.router上的路由以及之后通过app.include_router(...)挂载的子路由FastAPI 的 Bigger Applications 多文件组织方式 场景都会继承这一组全局依赖。可以推断因为应用自身的全部路由最终都收敛于这一个APIRouter把依赖放在这里等价于每个路由天然携带这份依赖这与官方文档它们会被应用于应用中所有的路径操作的描述完全吻合。这一实现细节也解释了使用要点全局依赖应在创建应用实例时就确定它面向的是整个应用统一策略若你只想对某一组路由或某个路由生效则应把dependencies声明在APIRouter()或路由装饰器上具体见下文。对一组路径操作施加依赖官方文档特别指出当应用逐渐变大、需要拆分到多个文件时你会学到如何为一组路径操作声明一个统一的dependencies参数——这正是 Bigger Applications - Multiple Files 章节的内容。简单预告其思路用APIRouter(prefix..., tags..., dependencies[Depends(...)])创建子路由则该子路由内所有路径操作都会执行这份依赖再用app.include_router(router)挂载到主应用。由此形成三种作用域从窄到宽的依赖声明层级单个路径操作装饰器 → 某个 APIRouter 分组 → 整个 FastAPI 应用。选择哪一个取决于校验逻辑的覆盖范围全站统一用全局依赖仅某个模块如/admin前缀下的管理接口需要时用分组依赖。测试与替换依赖覆盖依然可用全局依赖本质仍是普通依赖因此 FastAPI 的依赖覆盖机制app.dependency_overrides对它同样适用。在 fastapi/applications.py 中可以看到FastAPI实例持有dependency_overrides字典每个键为原始依赖可调用对象值为实际要调用的替代版本并把它作为dependency_overrides_provider传给了内部路由。这意味着在测试阶段你可以把挂在全局的verify_token等真实校验替换为测试用桩依赖从而绕开真实鉴权去测业务逻辑。这与仓库中tests/test_tutorial/test_dependencies/目录下多个教程测试的验证思路一致也适用于你为应用编写的自动化测试。小结全局依赖通过在FastAPI(dependencies[Depends(...), ...])传入应用于应用中所有路径操作含子路由每个请求进入业务函数前都会依次执行它们它复用普通依赖的全部能力声明 Header 等请求需求、依赖其他子依赖、抛出异常、返回值返回值不会被使用它适合全站统一鉴权、请求头校验等横切逻辑按模块分组时改用APIRouter(dependencies...)仅单个接口时用路径操作装饰器的dependencies官方示例与测试分别位于 docs_src/dependencies/tutorial012_an_py310.py 与 tests/test_tutorial/test_dependencies/test_tutorial012.py可对照阅读以加深理解。掌握这一机制后你便能用最小样板为整站统一施加进入业务逻辑前的约束让鉴权与校验策略集中管理、一处维护、处处生效。【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表