Python请求 - 重新验证后重试请求

wuj*_*jek 7 python python-requests

我使用Python3.5.1和Requests2.9.1.我的用例如下:我需要从服务T验证(获取令牌)并Authorization在向资源服务器R发出请求时将其用作标头的值.令牌在某个时刻到期并且需要获取新的令牌.

我有一个使用的应用程序requests,在启动时首先获取一个令牌并记住它 - 设置Session用于对R的请求.从那时起3分钟,一切都作为一个魅力.3分钟后,我得到unauthorized回复,因为令牌无效.

Session用于所有请求,除了要进行身份验证的请求; 此调用更新了要使用的其他请求的Authorization标头Session.

我创建了代码,以便在unauthorized检测到时自动重新进行身份验证,使用response钩子(仅在上面设置Session),这里是代码:

def __hook(self, res, *args, **kwargs):
    if res.status_code == requests.codes.unauthorized:
        print('Token expired, refreshing')
        self.auth() # sets the token on self.__session

        req = res.request
        print('Resending request', req.method, req.url, req.headers)
        req.headers['Authorization'] = self.__session.headers['Authorization'] # why is it needed?

        return self.__session.send(res.request)
Run Code Online (Sandbox Code Playgroud)

基本上,它甚至可以工作.但是有几个问题:

  1. 为什么有必要Authorization在请求上重新设置标头,即使会话已更新并用于重新发送原始请求?如果没有该行,应用程序将继续刷新令牌,因为新的令牌从未使用过,这可以在输出中看到,令牌是导致自动刷新的原始令牌.

  2. 如何使代码更加健壮,即防止无休止的递归(我不确定它是否可能在现实中,但是Authorization在重试的请求中设置标题的行将继续进行)?我正在考虑设置一个自定义标头,如果挂钩发现失败的请求有它,它将不会重新进行身份验证和重新发送.有更好的吗? 编辑:事实证明,如果配置错误,可能会得到(几乎)无限循环(毕竟它是递归的):令牌用于一个环境(如STAGING),但资源服务器来自另一个( TEST) - auth请求将成功,但令牌实际上对资源服务器不正确.目前我实现了上面提到的"特殊"头部解决方案.

这是一般的好方法还是有更适合任务的东西requests

Yes*_*esh 12

这是相同的解决方案,但不使用类

session = requests.Session()
session.headers.update({"Authorization": f"Bearer deliberate-wrong-token"})

def refresh_token(r, *args, **kwargs):
    if r.status_code == 401:
        logger.info("Fetching new token as the previous token expired")
        token = get_token()
        session.headers.update({"Authorization": f"Bearer {token}"})
        r.request.headers["Authorization"] = session.headers["Authorization"]
        return session.send(r.request, verify=False)

session.hooks['response'].append(refresh_token)
Run Code Online (Sandbox Code Playgroud)


wuj*_*jek 3

所以我联系了请求作者讨论一个不相关的问题并询问了这个问题,事实证明这种方法是好的。我所做的唯一更改是删除自定义标头(它确实有效并且也可以),现在我只需在重新发送请求之前取消注册挂钩内的响应挂钩。这打破了循环,一切都很好。