python-dependency-injector
python-dependency-injector copied to clipboard
How to make injection in middleware class of Fastapi/Starlette
Hi, i've been using this greate freamework in my project these days. In the docs of wiring, i see it's possible to wire a depedndency into a class directly,but in my project , which is based on fastapi, it's alwasy got an internal error when i try to inject the redis cliet into the middleware class (which is the feature provided by starlette).here is the simplified code :
(python3.9.5, | dependency-injector==4.38.0 | fastapi==0.74.1)
# main.py
from aioredis import from_url
from dependency_injector.containers import *
from dependency_injector.providers import *
from dependency_injector.wiring import Provide
from fastapi import FastAPI
from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint
from starlette.requests import Request
from starlette.responses import Response
async def init_redis_pool():
redis = from_url("redis://localhost:6379/0", max_connections=10)
try:
yield redis
finally:
await redis.close()
class Container(DeclarativeContainer):
wiring_config = WiringConfiguration(modules=[__name__])
redis = Resource(init_redis_pool)
class SomeMiddleware(BaseHTTPMiddleware):
redis = Provide[Container.redis]
async def dispatch(self, request: Request, call_next: RequestResponseEndpoint) -> Response:
print("========> hint SomeMiddleware <===========")
await self.redis.set("some_key", "some_value")
resp: Response = await call_next(request)
return resp
def create_app():
app = FastAPI()
app.container = Container()
@app.on_event("startup")
def startup():
app.container.init_resources()
@app.on_event("shutdown")
def shutdown():
app.container.shutdown_resources()
app.add_middleware(SomeMiddleware)
return app
application = create_app()
@application.get("/")
async def root():
return {"message": "Hello World"}
when i startup server with uvicorn main:application --reload and access http://127.0.0.1:8000/, i alwaye get such error msg:
...balblabla...
File ".\main.py", line 31, in dispatch
await self.redis.set("some_key", "some_value")
AttributeError: '_asyncio.Task' object has no attribute 'set'
did i miss something? :(