2

由于某些原因,我们选择了FastAPI,以便将其用作我们多模块生产的后端层。它的一个吸引人的特性是子应用程序,它可以帮助我们分离不同的模块,以使其更加模块化。但是我们担心官方文档中缺少一些可能的缺陷。有相当多的共同点——例如数据、服务等——我们需要通过插件、中间件和依赖注入在主模块和子模块之间共享它们。问题是:这个特性对于单独的模块是否足够好?所以:子应用程序是否从父应用程序继承中间件、插件和依赖注入?

感谢您分享您的经验。

官方文档中的示例代码

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)
4

1 回答 1

4

我认为文档对此非常清楚。

“挂载”意味着添加一个完全“独立”的应用程序。

无论如何,让我们继续从您的示例开始。

这就是我们为 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 的文档/subapi/docs,这里没什么意思。

那么,当我们添加这个时,我们应该期待什么?

subapi.mount("/app", app)

让我们再次运行它,但这次我们调用 subapi。

uvicorn my_app_name:subapi

我们期望看到什么?

  • 默认情况下,我们应该有 subapi 的文档/docs
  • 该应用程序的文档在/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说,您可以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'] = []

您添加的所有其他内容 etc 将独立工作,因为它们是完全不同的应用程序,因此您将安全地使用安装。

结论

  • 是的,他们将独立工作。
于 2020-10-12T20:36:23.953 回答