Warning: Bocadillo is now UNMAINTAINED. Users are recommended to migrate to a supported alternative, such as Starlette or FastAPI. Please see #344 for more information.
Hooks
Hooks allow you to call arbitrary code before and after a view is executed. They materialize as the @before()
and @after()
decorators located in the bocadillo.hooks
module.
These decorators operate on a hook function, which is an asynchronous function with the following signature: (req: Request, res: Response, params: dict) -> None
.
Example
from asyncio import sleep
from bocadillo import HTTPError, hooks
async def validate_has_my_header(req, res, params):
if "x-my-header" not in req.headers:
raise HTTPError(400)
async def show_response_content(req, res, params):
print(res.content)
@app.route("/message")
@hooks.before(validate_has_my_header)
@hooks.after(show_response_content)
async def get_message(req, res):
res.json = {"message": "hello"}
NOTE
The ordering of decorators is important: hooks should always be a view's first decorators.
Hooks and reusability
As a first level of reusability, you can pass extra positional or keyword arguments to @before()
and @after()
, and they will be handed over to the hook function:
async def validate_has_header(req, res, params, header):
if header not in req.headers:
raise HTTPError(400)
@app.route("/message")
@hooks.before(validate_has_header, header="x-my-header")
async def get_message(req, res):
pass
A hook just needs to be an asynchronous callable, so it can also be a class that implements __call__()
. This is another convenient way of building reusable hooks functions:
class RequestHasHeader:
def __init__(self, header: str):
self.header = header
async def __call__(self, req, res, params):
if self.header not in req.headers:
raise HTTPError(400)
@app.route("/message")
@hooks.before(RequestHasHeader("x-my-header"))
async def get_message(req, res):
pass
You can also use hooks on class-based views:
async def show_content_type(req, res, params):
print(res.headers["content-type"])
@app.route('/')
# applied on all method views
@hooks.after(show_content_type)
class Message:
@hooks.before(RequestHasHeader("x-my-header"))
async def get(self, req, res):
res.json = {"header": req.headers["x-my-header"]}
← Plugins Middleware →