Hooks
A "hook" is a mechanism that allows developers to intercept and modify the behavior of a request flow at specific points. It allows to register custom functions by using decorator that are executed when certain events or conditions occur.
All request hooks are optional. There are three (3) types of hooks and two (2) modes, which can be used together.
- Global hooks: These are run by the main python file. This requires the use of a main file.
- Request scripting hooks (local): These are defined on each the request script.
Each hook accepts:
Hook | Global | Request scripting |
---|---|---|
hooks.pre_request |
async/sync function | async/sync function |
hooks.post_request |
async/sync function | async/sync function |
hooks.test |
Not available | (sync only), unittest.TestCase class |
Hooks API
Global and request specific hooks receives the same arguments. But the way of call changes, use ctx.hooks
for local and zapy.requests.hooks
for global.
Pre-request hooks.pre_request
The httpx_args
parameter is a dict that should match the [email protected]
arguments, such as:
async with httpx.AsyncClient() as client:
client.request(**httpx_args)
For example:
from zapy.requests import hooks, HttpxArguments
@requests.hooks.pre_request
async def on_each_request(httpx_args: HttpxArguments):
httpx_args['auth'] = ('alice', 'ecila123')
print(httpx_args)
@ctx.hooks.pre_request
async def on_each_request(httpx_args):
httpx_args['auth'] = ('alice', 'ecila123')
print(httpx_args)
Post Request hooks.post_request
It receives a httpx response.
from zapy import requests, HttpxResponse
from zapy.store import use_store
store = use_store()
@requests.hooks.post_request
async def on_each_request(httpx_response: HttpxResponse):
store['payload'] = httpx_response.data
@ctx.hooks.post_request
async def on_response(httpx_response):
print("post_request")
ctx.store['payload'] = httpx_response.data
Test hooks.test
It allows providing assertions. This is specific for local hooks.
# test hook expects a unittest.TestCase class, cannot be async
import unittest
@ctx.hooks.test
class TestResponse(unittest.TestCase):
def test_status_code(self):
self.assertEqual(self.response.status_code, 200)
Using metadata
It's possible to enrich pre_request
and post_request
hooks by adding the extra arguments. The extra arguments have to be annotated with a type hint.
Allowed type hints:
Argument | Type | Description |
---|---|---|
Metadata |
Optional | Metadata object of the request |
ZapyRequest |
Optional | ZapyRequest object |
For example, to perform a conditional logic based on the metadata tags.
from zapy import requests
from zapy.base.models import Metadata
@requests.hooks.pre_request
async def on_each_request(httpx_args, metadata: Metadata):
if 'basic_auth' in metadata.tags:
httpx_args['auth'] = ('alice', 'ecila123')
from zapy.base.models import Metadata
@ctx.hooks.pre_request
async def on_pre_request(httpx_args, metadata: Metadata):
if 'basic_auth' in metadata.tags:
httpx_args['auth'] = ('alice', 'ecila123')