我有一个 FastAPI 应用程序,通过 Motor 连接 MongoDB。我在应用程序开始时打开 MongoDB 连接,并在最后使用
lifespan
: 将其关闭
from contextlib import asynccontextmanager
from fastapi import FastAPI, Request
from motor.motor_asyncio import AsyncIOMotorClient
@asynccontextmanager
async def lifespan(app):
mongo_client = AsyncIOMotorClient("mongo://")
mongo_db = mongo_client["mydb"]
yield {"db": mongo_db}
mongo_client.close()
app = FastAPI(lifespan=lifespan)
@app.get("/")
async def root(request: Request):
return request.state.db
在 Starlette 的最新版本之前,它曾经保存在
app.state
中,但现在它保存在 request.state
中。我必须从 db
对象内部访问 Request
变量的方式让我认为数据库客户端与每个请求一起被标记,并且可能容易受到来自客户端的漏洞的影响。
状态变量到底发生了什么?它真的与每个请求一起传输吗?或者将我的数据库客户端存储在这里是否安全?
在我的项目中,我使用中间件为数据库创建会话,如下所示:
# db_middleware.py
from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint
from starlette.responses import Response
from starlette.requests import Request
from fastapi import FastAPI
from db.session import Session
class DbMiddleware(BaseHTTPMiddleware):
def __init__(self, app: FastAPI) -> None:
super().__init__(app)
async def dispatch(
self, request: Request, call_next: RequestResponseEndpoint
) -> Response:
try:
request.state.db = Session()
response = await call_next(request)
finally:
if hasattr(request.state, "db") and request.state.db is not None:
request.state.db.close()
return response
# main.py
from fastapi import FastAPI
from middlewares.db_middleware import DbMiddleware
def create_app():
app = FastAPI()
app.add_middleware(DbMiddleware)
return app
app = create_app()
根据我的经验,通过这种方法可以控制在特定时间点应使用哪个数据库