19.FastAPI中间件
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了19.FastAPI中间件相关的知识,希望对你有一定的参考价值。
参考技术A 在FastAPI中,可以通过中间件在每个请求被特定的路径操作处理之前,以及在每个响应返回之前进行处理。FastAPI中间件是一个函数,其作用为:可以使用装饰器 @app.middleware("http") 来定义中间件,中间件函数的参数:
示例代码:
执行请求:
上面的代码中,通过中间件来计算请求的实际执行时间。
在使用中间件的情况下,FastAPI请求和响应的处理顺序为:中间件处理请求 -> 路由处理请求 -> 路由处理响应 ->中间件处理响应。代码示例:
执行请求:
后台print输出:
FastAPI的中间件可以拦截所有请求,同时也可以拦截所有响应,所以,一般情况下,可以针对请求和响应做一些统一的公共处理,比如:拦截请求后,记录用户的行为,或者对于特殊的处理进行鉴权等。
FastAPI 的应用挂载是如何工作的?
【中文标题】FastAPI 的应用挂载是如何工作的?【英文标题】:How does FastAPI's application mounting works? 【发布时间】:2021-01-27 02:03:59 【问题描述】:出于某些原因,我们选择了FastAPI,以便将其用作我们多模块生产的后端层。它的一个吸引人的特性是子应用程序,它可以帮助我们分离不同的模块,以使其更加模块化。但我们关注官方文档中可能存在的一些缺陷。有相当多的共同点——例如数据、服务等——我们需要通过插件、中间件和依赖注入在主模块和子模块之间共享它们。问题是:这个功能对于单独的模块是否足够好?等等:子应用程序是否从父应用程序继承中间件、插件和依赖注入?
感谢您分享您的经验。
the sample code in the official docs
from fastapi import FastAPI
app = FastAPI()
@app.get("/app")
def read_main():
return "message": "Hello World from main app"
subapi = FastAPI()
@subapi.get("/sub")
def read_sub():
return "message": "Hello World from sub API"
app.mount("/subapi", subapi)
【问题讨论】:
【参考方案1】:我认为文档很清楚。
“挂载”意味着添加一个完全“独立”的应用程序。
无论如何,让我们继续你的例子。
这就是我们为 subapi 的路由得到的。
["path":route.path for route in subapi.routes] = [
'path': '/openapi.json',
'path': '/docs',
'path': '/docs/oauth2-redirect',
'path': '/redoc',
'path': '/sub'
]
这就是我们得到的应用程序路线。
["path":route.path for route in app.routes] = ['path': '/openapi.json',
'path': '/docs',
'path': '/docs/oauth2-redirect',
'path': '/redoc',
'path': '/app',
'path': '/subapi'
]
这很有趣,因为我们的 subapi 没有继承 /app
,让我们继续前进,让事情变得更有趣,让我们用一个命令运行我们的应用程序
uvicorn my_app_name:app
正如预期的那样,我们在/docs
中有我们应用的文档
另外我们在/subapi/docs
有subapi的文档,这里没什么意思。
那么当我们添加这个时,我们应该期待什么?
subapi.mount("/app", app)
让我们再次运行它,但这次我们调用 subapi。
uvicorn my_app_name:subapi
我们期望看到什么?
默认情况下我们应该在/docs
中有subapi的文档
/app/docs
中的应用文档
是的,我们是对的,但事情从这里开始变得有趣。
现在我们有了一个像俄罗斯套娃这样的应用程序
当我们向/app/subapi/sub
发送请求时(提醒我们使用uvicorn my_app_name:subapi
运行我们的应用程序)
curl http://127.0.0.1:8000/app/subapi/sub
Out: "message":"Hello World from sub API"
看起来它工作正常,但让我们尝试更多。
/app/subapi/app/subapi/app/subapi/app/subapi/app/subapi/app/app
呢
curl http://127.0.0.1:8000/app/subapi/app/subapi/app/subapi/app/subapi/app/subapi/app/app
Out: "message":"Hello World from main app"
你感到困惑吗?别这样,让我解释一下。
当您挂载子应用程序时,FastAPI 会使用 ASGI 规范中称为 root_path
的机制来处理已挂载的应用程序
root_path
做了什么以及为什么上面的例子有效?
直截了当的root_path
说,您可以从您的root_path
到达您在app.routes
中定义的所有路线,让我们将其可视化。
现在我们的root_path
是/app
/app/
让我们添加subapi,它就变成了我们的root_path
。
/app/subapi/
让我们再次添加应用,它变成了我们的root_path
/app/subapi/app
注意:上面的示例之所以有效,是因为我们将两个应用安装在一起。
你不满意,你说如果我添加一个中间件,会发生什么?
容易回答,不会继承。
让我用一个简单的例子来解释一下,我将为我的 subapi 添加一个中间件。
from fastapi.middleware.cors import CORSMiddleware
subapi.add_middleware(CORSMiddleware)
您的应用程序的所有数据都在 __dict__
中
所以我们可以通过检查 'user_middleware' 键轻松找出差异。
subapi.__dict__['user_middleware'] = [Middleware(CORSMiddleware)]
app.__dict__['user_middleware'] = []
您添加的所有其他内容 etc 将独立工作,因为它们是完全不同的应用程序,因此您将安全地使用安装。
结论
是的,他们将独立工作。【讨论】:
非常感谢您的完整回答。我确实可以从你的回答中得到比我所要求的更多的教训。看来我应该打包我的依赖项,以便将它们分别注入每个子应用程序中。 不客气!我很高兴它有帮助。是的,在某些情况下它非常有用,我不完全知道您的用例是什么,但是,您似乎想使用大量中间件和依赖注入,也许您应该考虑创建自己的 APIRouter class 这似乎是个好建议。它可以集成我将尝试的大多数中间件。再次感谢。以上是关于19.FastAPI中间件的主要内容,如果未能解决你的问题,请参考以下文章