Pre Hooking / Post Hooking¶
In ahttp_client, hooking means refining data before and after an HTTP request is received. A hooking supports session unit hooking and request unit hooking.
A hooking is used as follows.
- Before Hook (Pre-request):
Set up the required HTTP component (e.g. authorization).
Validate that the correct arguments are given.
- After Hook (Post-request)
Parse the raw response data into a data class.
Act based on the HTTP status code.
Note
This page only covers the session-level before_request/after_request hooks and the request-level before_hook/after_hook decorators. For how retries interact with after_request, see Retry. For the HTTPException hierarchy a hook can raise, see Exception.
Session Hooking¶
A Session unit hooking is created by overridding a method.
1class GithubService(AsyncSession):
2 def __init__(self, token: str):
3 self._token = token # Private Attribute
4 super().__init__("https://api.github.com", aiohttp.ClientSession)
5
6 # overriding before_request method
7 async def before_request(self, req_obj: RequestCore, path: str):
8 req_obj.headers["Authorization"] = self._token
9 req_obj.headers["Accepts"] = "application/vnd.github+json;"
10 return req_obj, path
11
12 # overriding after_request method
13 async def after_request(self, response: Response):
14 if response.status != 200:
15 raise HTTPException()
16 return response
17
18 @request("GET", "/users/{user}/repos")
19 async def list_repositories(
20 self, response: Response, user: Annotated[str, Path]
21 ) -> list[dict[str, Any]]:
22 return response.json()
GithubService overrides before_request and after_request directly.
The token is stored as a private attribute, and before_request inserts it into the header. Whenever a method on the object is called, such as list_repositories, before_request runs first and adds the HTTP components a request needs.
after_request runs once the HTTP request finishes and checks the status code. A status other than 200 (OK) raises HTTPException, a predefined exception (see Exception).
Request Hooking¶
A request unit hooking is created using the decorating method.
1token = "GITHUB TOKEN"
2
3@AsyncSession.single_session("https://api.github.com", aiohttp.ClientSession)
4@request("GET", "/repos/{user}/{repo}/topics")
5async def repository_topic(
6 session: AsyncSession,
7 response: Response,
8 user: Annotated[str, Path],
9 repo: Annotated[str, Path]
10) -> list[str]:
11 return response.json()["names"]
12
13# before_hook method
14@repository_topic.before_hook
15async def before_hook(session: AsyncSession, req_obj: RequestCore, path: str):
16 req_obj.headers["Authorization"] = token
17 req_obj.headers["Accepts"] = "application/vnd.github+json;"
18 return req_obj, path
19
20# after_hook method
21@repository_topic.after_hook
22async def after_hook(session: AsyncSession, response: Response):
23 if response.status != 200:
24 raise HTTPException()
25 return response
repository_topic fetches the topics of a repository, and its before_hook/after_hook decorators define the hooking right on that same method.
before_hook inserts what the request needs (an authorization key, for example) before repository_topic makes the HTTP call.
after_hook validates the response before the request function parses the JSON.
Warning
A request-level after_hook always runs after any Retry attempts have finished. It is not retried itself, even if it raises an exception listed in retry_on.