Class-Based Handlers for AIOHTTP¶
Class-based handlers in Wireup provide a new mechanism for efficient dependency injection for AIOHTTP applications. They optimize performance by managing dependencies at startup rather than per request. Dependencies injected in the init method are zero-cost.
For the lowest-overhead request path, configure AIOHTTP integration with middleware_mode=False. Class-based handlers
still work with middleware_mode=True, but that mode adds AIOHTTP middleware so get_request_container() can be
accessed globally during request handling.
Key Benefits¶
- Request Performance: Zero overhead from dependency resolution during request handling.
- Stateful Handlers: Maintain state across requests.
- Route set: Group relevant resource endpoints together
Example¶
class GreeterHandler:
router = web.RouteTableDef() # (1)!
def __init__(self, greeter: GreeterService) -> None: # (2)!
self.greeter = greeter
self.counter = 0
@router.get("/greet")
async def get_thing(
self,
request: web.Request, # (3)!
auth_service: Injected[AuthenticationService], # (4)!
) -> web.Response:
self.counter += 1
return web.json_response(
{
"greeting": self.greeter.greet(
request.query.get("name", "world")
),
"counter": self.counter,
}
)
- The class must contain a
web.RouteTableDefinstance namedrouter. Use it to decorate routes inside this class. - When injecting in the constructor the
Injectedsyntax is not required. - Like every AIOHTTP request handler, the first argument must be
web.Request. - Other scoped/transient dependencies can be requested in the routes. Here the
Injected[T]annotation is required.
wireup.integration.aiohttp.setup(
container,
app,
handlers=[GreeterHandler],
middleware_mode=False, # Recommended for the zero-overhead path
)
Overriding: Handlers are created once on startup, their dependencies cannot be overridden once the application
starts. If you need to override dependencies in the handler's __init__, then it must be done before application
startup.