dioxide.fastapi¶
FastAPI integration for dioxide dependency injection.
This module provides seamless integration between dioxide’s dependency injection container and FastAPI applications. It enables:
Single middleware setup:
app.add_middleware(DioxideMiddleware, profile=...)Request scoping: Automatic
ScopedContainerper HTTP requestClean injection:
Inject(Type)wrapper for FastAPI’sDepends()Lifecycle management: Container start/stop with FastAPI lifespan
- Quick Start:
Set up dioxide in your FastAPI app:
from fastapi import FastAPI from dioxide import Profile from dioxide.fastapi import DioxideMiddleware, Inject app = FastAPI() app.add_middleware(DioxideMiddleware, profile=Profile.PRODUCTION) @app.get('/users/me') async def get_me(ctx: RequestContext = Inject(RequestContext)): return {'request_id': str(ctx.request_id)} @app.get('/users') async def list_users(service: UserService = Inject(UserService)): return await service.list_all()
- Request Scoping:
The middleware creates a
ScopedContainerfor each HTTP request. This enables REQUEST-scoped components to be shared within a single request but fresh for each new request:from dioxide import service, Scope @service(scope=Scope.REQUEST) class RequestContext: def __init__(self): import uuid self.request_id = str(uuid.uuid4()) # In route handlers: @app.get('/test') async def test(ctx: RequestContext = Inject(RequestContext)): # ctx.request_id is unique per request # but shared if resolved multiple times within same request return {'request_id': ctx.request_id}
- Lifecycle Management:
The middleware handles container lifecycle automatically:
from dioxide import adapter, lifecycle, Profile @adapter.for_(DatabasePort, profile=Profile.PRODUCTION) @lifecycle class PostgresAdapter: async def initialize(self) -> None: self.engine = create_engine(...) print('Database connected') async def dispose(self) -> None: await self.engine.dispose() print('Database disconnected') # When FastAPI starts: container.start() initializes adapters # When FastAPI stops: container.stop() disposes adapters
See also
DioxideMiddleware- The main integration middlewareInject()- Dependency injection helper for route handlersdioxide.container.Container- The DI containerdioxide.container.ScopedContainer- Request-scoped container
Classes¶
ASGI middleware that integrates dioxide with FastAPI. |
Functions¶
|
Create a FastAPI dependency that resolves from dioxide container. |
Module Contents¶
- class dioxide.fastapi.DioxideMiddleware(app, profile=None, container=None, packages=None)[source]¶
ASGI middleware that integrates dioxide with FastAPI.
This middleware handles both:
Lifecycle management: Container
start()/stop()via ASGI lifespanRequest scoping: Creates
ScopedContainerper HTTP request
The middleware intercepts ASGI events:
lifespan: Scans components and starts/stops the containerhttp: Creates a scoped container for each request
- Usage:
Basic setup with profile:
from fastapi import FastAPI from dioxide import Profile from dioxide.fastapi import DioxideMiddleware app = FastAPI() app.add_middleware(DioxideMiddleware, profile=Profile.PRODUCTION)
With custom container:
from dioxide import Container, Profile from dioxide.fastapi import DioxideMiddleware my_container = Container() app = FastAPI() app.add_middleware( DioxideMiddleware, container=my_container, profile=Profile.TEST, )
With package scanning:
app.add_middleware( DioxideMiddleware, profile=Profile.PRODUCTION, packages=['myapp.services', 'myapp.adapters'], )
- Parameters:
app (Any) – The ASGI application to wrap
profile (dioxide.profile_enum.Profile | str | None) – Profile to scan with (e.g.,
Profile.PRODUCTION)container (dioxide.container.Container | None) – Optional Container instance. If not provided, uses the global
dioxide.containersingleton.packages (list[str] | None) – Optional list of packages to scan for components.
See also
Inject()- How to inject dependencies in routesdioxide.container.ScopedContainer- The scoped container
- dioxide.fastapi.Inject(component_type)[source]¶
Create a FastAPI dependency that resolves from dioxide container.
This function wraps FastAPI’s
Depends()to resolve dependencies from the dioxide container. It automatically uses the correct scope:SINGLETON: Resolved from parent container (shared)
REQUEST: Resolved from request scope (fresh per request)
FACTORY: New instance each resolution
- Parameters:
component_type (type[T]) – The type to resolve from the container
- Returns:
A FastAPI
Depends()object that resolves the component- Return type:
Any
Example
Basic usage:
from dioxide.fastapi import Inject @app.get('/users') async def list_users(service: UserService = Inject(UserService)): return await service.list_all()
Multiple dependencies:
@app.get('/dashboard') async def dashboard( users: UserService = Inject(UserService), analytics: AnalyticsService = Inject(AnalyticsService), ): return { 'users': await users.count(), 'visits': await analytics.total_visits(), }
Request-scoped dependencies:
from dioxide import service, Scope @service(scope=Scope.REQUEST) class RequestContext: def __init__(self): self.request_id = str(uuid.uuid4()) @app.get('/test') async def test(ctx: RequestContext = Inject(RequestContext)): # ctx is unique per request return {'request_id': ctx.request_id}
- Raises:
RuntimeError – If called without
DioxideMiddlewarebeing configured- Parameters:
component_type (type[T])
- Return type:
Any
Note
The function name is capitalized (
Inject) to match the convention of FastAPI’sDepends,Query,Body, etc.See also
DioxideMiddleware- Must be added firstdioxide.container.ScopedContainer- How scoping works