Modify request params with custom authentication
python, python-requests
Solution
Indeed, a `PreparedRequest` is now passed in, and the URL query string is already set from the parameters.
However, the `PreparedRequest.prepare_url()` method will let you update the URL with additional parameters:
class APIAuth(requests.auth.AuthBase):
def __call__(self, request):
api_secret = settings.API_SHARED_SECRET
api_key = settings.API_KEY
request.prepare_url(request.url, dict(
api_key=api_key,
timestamp=int(time.time()*1000)))
signature = base64.b64encode(hmac.new(
api_secret,
msg=unquote(request.full_url),
digestmod=hashlib.sha256
).digest()).decode()
request.headers['Authorization'] = "signature {0}".format(signature)
return request
Demo:
>>> import requests
>>> prepared = requests.Request(url='http://httpbin.org/get').prepare()
>>> prepared.url
'http://httpbin.org/get'
>>> prepared.prepare_url(prepared.url, {'foo': 'bar', 'spam': 42})
>>> prepared.url
'http://httpbin.org/get?foo=bar&spam=42'
>>> prepared.prepare_url(prepared.url, {'monty': 'python'})
>>> prepared.url
'http://httpbin.org/get?foo=bar&spam=42&monty=python'
By passing in `prepared.url` the URL is updated to add the extra parameters. New parameters are always additive; if a new parameter has the same name as an already added parameter the old parameter is not removed.
Problem
I've just upgraded my requests library to 2.3.0 (from 0.14.0), and my custom authentication is no longer working. The issue is that the custom authentication we use appends an API key and a timestamp to the request, so all of our helper methods don't need to do it. ``` class APIAuth(requests.auth.AuthBase): def __call__(self, request): api_secret = settings.API_SHARED_SECRET api_key = settings.API_KEY request.params.update(dict( api_key=api_key, timestamp=int(time.time()*1000))) signature = base64.b64encode(hmac.new( api_secret, msg=unquote(request.full_url), digestmod=hashlib.sha256 ).digest()).decode() request.headers['Authorization'] = "signature {0}".format(signature) return request ``` The error: ``` AttributeError: 'PreparedRequest' object has no attribute 'params' ``` Prepared request does not allow modification of the params dict, presumably because it has already been constructed. Is there a simple way to update the params dict from our custom authentication that leaves any existing params intact? Or do I have to bite the bullet and add these two parameters for every request method?