Search code examples
pythonproxypython-requestspython-decorators

How to force external python packages use requests with proxy


I'm writing a job to download some reports from an API. There is an external python package which does this for me by simply use:

from module import Api

api = Api(token='token')
api.download_data(save_to='file_name.csv')

But this Api is critical for the caller IP address (some reports are available only for specific location), so I am forced to change my location either via VPN or socks proxy.

There are few reports I have to download from different locations, so I decided to use proxies.

I mentioned that under the hood my module uses requests library to retrieve the data.

How can I force requests lib to use my proxies for external functions?


Solution

  • It turned out that this can be implemented via old-style decorators pretty simple:

    # config.py
    HTTP_METHODS = ['get', 'post', 'put', 'delete', 'head', 'patch', 'options']
    
    # helper.py
    import requests
    
    from config import HTTP_METHODS
    
    
    def _add_proxy(http_req, country):
        # retrieve proxy settings for the country
        proxy = get_proxy(country)
        def wrapper(*args, **kwargs):    
            kwargs['proxies'] = proxy
            return http_req(*args, **kwargs)
        return wrapper
    
    
    def patch_requests_with_proxy(country):
        for m in HTTP_METHODS:
            setattr(requests, m, _add_proxy(getattr(requests, m), country))
    
    

    That usage of my new script will be:

    from module import Api
    from helper import patch_requests_with_proxy
    
    
    api = Api(token='token')
    patch_requests_with_proxy('ContryName1')
    api.download_data(save_to='file_name1.csv')
    
    patch_requests_with_proxy('ContryName2')
    api.download_data(save_to='file_name2.csv')
    

    My script is job-based, so I don't need any kind of unpatch functionality.