Flask (WSGI)¶
Flask integration uses Flask’s built-in request-local context and does not require middleware.
You register request access once with add_request_context(container), then use
@resolver_context.inject(scope=Scope.REQUEST) on views.
Minimal setup¶
The integration consists of two pieces:
diwire.integrations.flask.add_request_context()registersflask.Requestin yourdiwire.Container.diwire.integrations.flask.get_request()resolves the current request from Flask’s active request context and raisesdiwire.exceptions.DIWireIntegrationErrorwhen used outside a request.
from flask import Flask, Request
from diwire import Container, Injected, Lifetime, Scope, resolver_context
from diwire.integrations.flask import add_request_context
app = Flask(__name__)
container = Container()
add_request_context(container)
class RequestService:
def run(self) -> str:
return "ok"
container.add(
RequestService,
provides=RequestService,
scope=Scope.REQUEST,
lifetime=Lifetime.SCOPED,
)
@app.get("/health")
@resolver_context.inject(scope=Scope.REQUEST)
def health(service: Injected[RequestService]) -> dict[str, str]:
return {"status": service.run()}
Inject flask.Request in handlers and services¶
from dataclasses import dataclass
from flask import Flask, Request
from diwire import Container, Injected, Lifetime, Scope, resolver_context
from diwire.integrations.flask import add_request_context
app = Flask(__name__)
container = Container()
add_request_context(container)
@dataclass
class RequestPathService:
request: Request
def path(self) -> str:
return self.request.path
container.add(
RequestPathService,
provides=RequestPathService,
scope=Scope.REQUEST,
lifetime=Lifetime.SCOPED,
)
@app.get("/path")
@resolver_context.inject(scope=Scope.REQUEST)
def path_handler(
request: Injected[Request],
service: Injected[RequestPathService],
) -> dict[str, str]:
return {
"direct_path": request.path,
"service_path": service.path(),
}
How it works¶
Flask opens a request context and exposes
flask.requestas a request-local proxy.@resolver_context.inject(scope=Scope.REQUEST)opens a request scope, resolvesInjected[...]parameters, and calls your view.add_request_context(container)makesflask.Requestresolvable by reading the active Flask request proxy.When the view returns, the injected wrapper closes the request scope and runs scoped cleanup.
Testing¶
In-process tests: use
app.test_client()and calladd_request_context(container)in app setup.End-to-end (Docker Compose): run
make test-e2e-flask.