uplink icon indicating copy to clipboard operation
uplink copied to clipboard

Expose a request hook: i.e., @response_handler for requests

Open prkumar opened this issue 4 years ago • 5 comments

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.

prkumar avatar Jan 19 '20 22:01 prkumar

Any progress on this?

ghandic avatar Nov 28 '22 00:11 ghandic

@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.

mure avatar Nov 29 '22 23:11 mure

@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

wabiloo avatar May 19 '23 06:05 wabiloo

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

ghandic avatar May 19 '23 06:05 ghandic

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()

selimt avatar May 19 '23 16:05 selimt