ross / requests-futures

Asynchronous Python HTTP Requests for Humans using Futures
Other
2.11k stars 152 forks source link

How do we pass arguments to the hooks? #117

Closed 842Mono closed 2 years ago

842Mono commented 2 years ago

When we specify a hook like this:

session.get('http://some_url', hooks={'response': response_hook})

Is there a way to pass an argument to that response_hook function?

ross commented 2 years ago

Like most other functionality requests_futures hooks are straight pass throughs of the underlying requests library https://docs.python-requests.org/en/latest/user/advanced/#event-hooks

Probably the easiest way to tie data to a specific request is to use an inline function:

#!/usr/bin/env python

from pprint import pprint
import requests

def get(url, params, hook_arg):

    def hook(response, *args, **kwargs):
        pprint({
            'hook_arg': hook_arg,
            'request': response.request,
            'response': response,
            'json': response.json(),
            'args': args,
            'kwargs': kwargs,
        })

    requests.get(url, params=params, hooks={'response': [hook]})

get('https://nghttp2.org/httpbin/get', {'call': 'first'}, 42)
get('https://nghttp2.org/httpbin/get', {'call': 'second'}, 43)
$ ./args.py
{'args': (),
 'hook_arg': 42,
 'json': {'args': {'call': 'first'},
          'headers': {'Accept': '*/*',
                      'Accept-Encoding': 'gzip, deflate',
                      'Host': 'nghttp2.org',
                      'User-Agent': 'python-requests/2.26.0'},
          'origin': 'xx.xx.xx.xx',
          'url': 'https://nghttp2.org/httpbin/get?call=first'},
 'kwargs': {'cert': None,
            'proxies': OrderedDict(),
            'stream': False,
            'timeout': None,
            'verify': True},
 'request': <PreparedRequest [GET]>,
 'response': <Response [200]>}
{'args': (),
 'hook_arg': 43,
 'json': {'args': {'call': 'second'},
          'headers': {'Accept': '*/*',
                      'Accept-Encoding': 'gzip, deflate',
                      'Host': 'nghttp2.org',
                      'User-Agent': 'python-requests/2.26.0'},
          'origin': 'xx.xx.xx.xx',
          'url': 'https://nghttp2.org/httpbin/get?call=second'},
 'kwargs': {'cert': None,
            'proxies': OrderedDict(),
            'stream': False,
            'timeout': None,
            'verify': True},
 'request': <PreparedRequest [GET]>,
 'response': <Response [200]>}

You also have full access to the request object so anything associated with it will be accessible.

842Mono commented 2 years ago

Okay thank you. I used a closure. Not sure what's the use of params=params here. I thought that this is how I could pass parameters.

ross commented 2 years ago

Not sure what's the use of params=params here.

It was just to pass different params into the get so that they'd show up in the httpbin output.