(Как) я могу отправлять (подготовленные) запросы с помощью requests .OAuth2Session?

#python #python-3.x #oauth-2.0 #python-requests #requests-oauthlib

#python #python-3.x #oauth-2.0 #python-запросы #запросы-oauthlib

Вопрос:

При запуске следующего (при замене example.com на наш API, очевидно)

 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
  

следующее возвращает <Response [200]> :

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

Но это возвращает <Response [401]> :

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

Как я могу повторно использовать исходный Request объект при отправке его через OAuth2Session ?

Ответ №1:

OAuth2Session Реализация не переопределяет методы Session.prepare_request() or Session.send() , только Session.request() была специализированной. Это потому, что он обрабатывает автоматическое обновление тем же методом, требуя отправки большего количества запросов.

Для поддержки изменения этих запросов библиотека предлагает средство перехвата соответствия, где в определенные моменты процесса вызывается перехват, который может изменять детали запроса. Объект OAuth2Session, начиная с версии 0.4.0, поддерживает 3 разных перехвата:

  • access_token_response : передан ответ на запрос токена доступа, прежде чем ответ будет проанализирован для извлечения токена.
  • refresh_token_response : передан ответ на запрос токена обновления, опять же, до того, как ответ будет проанализирован.
  • protected_request : передал URL, заголовки и тело запросов, используемых для доступа к защищенным ресурсам (таким образом, запрос, который должен включать действительный токен).

Несколько включенных исправителей соответствия используют эти перехваты для добавления недостающих элементов из ответов от определенных поставщиков и для обновления исходящих запросов, когда определенные API отклоняются от стандарта OAuth в отношении того, как они обрабатывают токены.

protected_request здесь интересный хук, поскольку передаются те же данные, которые вы обычно хотели бы изменить при использовании шаблона request.Request() / session.prepare_request() / session.send() . Вы можете изменить те же данные запроса в несколько иной упаковке, прежде чем клиент oauthlib сможет добавить токен к этим данным.

Тем не менее, если вам не нужно использовать автоматическое обновление или вы можете самостоятельно обрабатывать истечение срока действия токена, вы можете напрямую получить доступ к oauthlib клиенту, который OAuth2Sesson переносится. Если вы уже получили токен, вы можете подписать свой запрос перед подготовкой с помощью:

 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)
  

При этом напрямую используется add_token() метод клиента oauthlib.

Комментарии:

1. Имея подготовленный запрос, подобный этому: req = requests.Request('GET', BASE_URL, params=params) как я могу его затем отправить? Я использовал dir(req) , но, похоже, у него нет send метода. Обязательно ли мне передавать его через Session объект? Это то, что requests.get / requests.post делать за кулисами? Они создают сеанс и передают подготовленный запрос в сеанс?

2. @M.Ionut: да, вы должны передать подготовленный запрос session.request() . Это то, что делает пример кода в моем ответе ( client является экземпляром OAuth2Session here , который является подклассом Session ).

3. @M.Ionut: под прикрытием Session.request() создает Request экземпляр, использует Session.prepare() его для превращения в a PreparedRequest , затем передает последний Session.send() . Session.request() это что Session.get() / Session.post() и т.д. все откладывается на.