blackbull.middleware.utils¶
blackbull.middleware.utils
¶
Utilities for middleware authors.
Public API:
- as_middleware: decorator that normalises the send callable so inner
send wrappers defined by the middleware always receive a single native
representation — NativeResponse on the HTTP path (H1 and H2), plain
ASGI event dicts only at the external-host edge — never raw
Response objects. Works on both async middleware functions and
middleware classes (decorates __call__).
as_middleware(target)
¶
Decorator that marks an async function or class as BlackBull middleware.
Wraps call_next so any send callable the middleware passes to it is
automatically normalised — Response/JSONResponse objects are converted to
NativeResponse before reaching the middleware's inner send wrapper.
The wrapper therefore only ever sees the native representation
(NativeResponse on the HTTP path — H1 and H2).
Applied to an async function (signature (conn, receive, send, call_next))::
@as_middleware
async def timing_mw(conn, receive, send, call_next):
async def timed_send(event):
# event is a NativeResponse on the HTTP path
await send(event)
await call_next(conn, receive, timed_send)
Applied to a class whose __call__ is the middleware coroutine::
@as_middleware
class Cache:
async def __call__(self, conn, receive, send, call_next):
async def cap_send(event):
# event is a NativeResponse on the HTTP path
...
await call_next(conn, receive, cap_send)
Power users who need to handle raw send arguments (e.g. because their
middleware is used in a context where no simplified handlers are registered)
should omit this decorator — their call_next is then wired directly to
the next handler with no extra wrapping.