(如何)我可以使用 requests.OAuth2Session 发送(准备好的)请求?

(How) can I send (prepared) requests with requests.OAuth2Session?

当运行以下(同时用我们的API替换example.com时,显然)

req = Request('GET', 'https://example.com')
# client is a customized OAuth2Session
client.authorize(self.username, self.password, self.auth_key)
print(self.client.authorized) # True

以下returns<Response [200]>:

response = client.request(req.method, req.url)

但是这个returns<Response [401]>:

 prepped = client.prepare_request(req)
 response = client.send(prepped)

如何在通过 OAuth2Session 发送原始 Request 对象时重用它?

OAuth2Session 实现不会覆盖 Session.prepare_request() or Session.send() methods, only Session.request() 已经专门化。那是因为它以相同的方法处理auto-refreshing,需要发送更多的请求。

为了支持更改这些请求,该库提供了一个 合规挂钩 工具,在该过程中的特定点调用一个挂钩可以更改请求的详细信息。 OAuth2Session object,从 0.4.0 版本开始,支持 3 种不同的钩子:

  • access_token_response:传递来自 access token request 的响应,然后解析响应以提取令牌。
  • refresh_token_response:在解析响应之前再次传递来自 refresh token request 的响应。
  • protected_request:传递了用于访问受保护资源的请求的 url、headers 和 body(因此请求应包含有效令牌)。

几个 included compliance fixers 使用这些挂钩来添加来自某些提供者的响应中缺少的元素,并在某些 API 偏离 OAuth 标准的令牌处理方式时更新传出请求。

protected_request 是这里有趣的钩子,因为它传递的数据与您在使用 request.Request() / session.prepare_request() / session.send() 模式时通常想要更改的数据相同.在 oauthlib 客户端将令牌添加到该数据之前,您可以在稍微不同的包装中更改相同的请求数据。

也就是说,如果您不需要使用 auto-refreshing 或者可以自己处理令牌过期,您可以访问 oauthlib client that the OAuth2Sesson wraps, directly. Provided you already fetched a token,您可以在准备之前签署您的请求:

from oauthlib.oauth2 import TokenExpiredError

req = Request('GET', 'https://example.com')
try:
    req.url, req.headers, req.data = client._client.add_token(
        req.url, http_method=req.method, body=req.data, headers=req.headers
    )
except TokenExpiredError:
    # handle token expiration
    pass

else:
    prepped = client.prepare_request(req)
    response = client.send(prepped)

这里直接使用oauthlib客户端的add_token() method