uplink
uplink copied to clipboard
Expose a request hook: i.e., @response_handler for requests
Is your feature request related to a problem? Please describe. Creating this issue as a follow up of a question asked on gitter:
is there any way to log all the executed requests?
Currently, this is not easily doable. Listening for requests is technically possible by using a RequestTemplate
. You could define your own RequestTemplate
subclass and implement the before_request
method to log each request sent. For an example of how to define and register a RetryTemplate, you can take a look at the retry
decorator.
Describe the solution you'd like
We could expose a @request_handler
decorator that enables users to add hooks that execute before a request is sent.
Additional context As part of this work, we should define and expose a simplified interface of the user's request.
Any progress on this?
@prkumar
What's the difference between a MethodAnnotation
with a modify_request
implementation and a RequestTemplate
with a before_request
hook?
I'm trying to add some dynamic behavior to requests (e.g. conditionally add a header) and I'm not sure what approach to take.
@prkumar i could really do with this too… for the same reason: logging. In particular logging of requests that may fail (and therefore i can’t use response.request in the response_handler
If you're using httpx you can do this really nicely. I have a dummy example repo showing this with a client here https://github.com/ghandic/httpx-audit/blob/main/app/custom_client.py
FYI, in case it helps, we've added a request logger to our client code:
from uplink.clients.io import RequestTemplate
class RequestLogger(RequestTemplate):
"""Template class for logging API requests."""
def before_request(self, request):
LOGGER.debug("%s %s" % (request[0], request[1]))
for k, v in request[2].items():
if k == "headers":
continue
LOGGER.debug("%s: %s" % (k, v))
# noinspection PyPep8Naming
class request_handler(decorators.MethodAnnotation): # noqa: N801
"""Request handler for tracing API calls to the server.
It is based on the uplink.retry.retry decorator.
It registers the RequestLogger template to log request
url, json and params.
"""
def modify_request(self, request_builder):
"""Add the request template to the request builder.
Args:
request_builder (:obj:`uplink.helpers.RequestBuilder`): Request builder.
"""
request_builder.add_request_template(self._create_template(request_builder))
def _create_template(self, request_builder):
"""Instantiate and return the request template.
Args:
request_builder (:obj:`uplink.helpers.RequestBuilder`): Request builder.
Returns:
RequestLogger: Request template instance which handles logging before the request.
"""
return RequestLogger()