问题描述
出于某些原因,我们选择了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)
解决方法
我认为文档对此非常清楚。
“安装”是指添加一个完全“独立”的应用程序。
无论如何,让我们继续您的示例。
这是我们的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': '/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
中的应用文档
是的,我们是对的,但是从这里开始事情变得有趣了。
现在我们有了Matryoshka娃娃之类的应用程序
当我们向/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
说,您可以从app.routes
到达root_path
中定义的所有路线,让我们直观地看到。
现在我们的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'] = []
您添加的所有其他内容等都将独立运行,因为它们是下面的完全不同的应用程序,因此您可以安全地使用挂载。
结论
- 是的,他们将独立工作。