使用自定义身份验证修改请求参数

时间:2014-05-31 06:53:04

标签: python python-requests

我刚刚将我的请求库升级到2.3.0(从0.14.0开始),我的自定义身份验证不再有效。问题是我们使用的自定义身份验证会在请求中附加API密钥和时间戳,因此我们所有的帮助方法都不需要这样做。

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

错误:

AttributeError: 'PreparedRequest' object has no attribute 'params'

准备好的请求不允许修改params dict,大概是因为它已经被构造了。有没有一种简单的方法来更新我们的自定义身份验证中的params dict,使任何现有的params保持不变?或者我必须咬紧牙关并为每个请求方法添加这两个参数?

1 个答案:

答案 0 :(得分:3)

实际上,现在传入PreparedRequest,并且已经从参数设置了URL查询字符串。

但是,PreparedRequest.prepare_url() method会让您使用其他参数更新网址:

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

演示:

>>> 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'

通过传递prepared.url,URL会更新以添加额外参数。新参数始终是添加;如果新参数与已添加的参数具有相同的名称,则不会删除旧参数。