retry HTTP requests 3 times (fixes #21783)
Retry is applied to access token request and user info requests (through OAuth2Session). There is a small exponential backoff of 0.5 and 1s. Also decrease log level of message for failure of retrieval of the access token or the user info to the level WARNING, that's never been a problem for the user, as he was correctly redirected to its origin (usually and IdP endpoint).
This commit is contained in:
parent
738066a5d9
commit
c701e61043
|
@ -5,6 +5,10 @@ import json
|
|||
import datetime
|
||||
import uuid
|
||||
|
||||
import requests
|
||||
from requests.adapters import HTTPAdapter
|
||||
from requests.packages.urllib3.util.retry import Retry
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.conf import settings
|
||||
from django.shortcuts import resolve_url
|
||||
|
@ -158,3 +162,24 @@ def apply_user_info_mappings(user, user_info):
|
|||
tags.add(mapping['tag'])
|
||||
if save_user:
|
||||
user.save()
|
||||
|
||||
|
||||
def requests_retry_session(
|
||||
retries=3,
|
||||
backoff_factor=0.5,
|
||||
status_forcelist=(500, 502, 504),
|
||||
session=None,
|
||||
):
|
||||
'''Create a requests session which retries after 0.5s then 1s'''
|
||||
session = session or requests.Session()
|
||||
retry = Retry(
|
||||
total=retries,
|
||||
read=retries,
|
||||
connect=retries,
|
||||
backoff_factor=backoff_factor,
|
||||
status_forcelist=status_forcelist,
|
||||
)
|
||||
adapter = HTTPAdapter(max_retries=retry)
|
||||
session.mount('http://', adapter)
|
||||
session.mount('https://', adapter)
|
||||
return session
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import uuid
|
||||
import requests
|
||||
import logging
|
||||
import json
|
||||
import urlparse
|
||||
import urllib
|
||||
import requests
|
||||
|
||||
from requests_oauthlib import OAuth2Session
|
||||
|
||||
|
@ -86,10 +86,11 @@ def resolve_access_token(authorization_code, redirect_uri, logger):
|
|||
}
|
||||
logger.debug('access token request %s', data)
|
||||
try:
|
||||
response = requests.post(
|
||||
session = utils.requests_retry_session()
|
||||
response = session.post(
|
||||
app_settings.token_url, data=data,
|
||||
verify=app_settings.verify_certificate,
|
||||
allow_redirects=False, timeout=10)
|
||||
allow_redirects=False, timeout=3)
|
||||
if response.status_code != 200:
|
||||
try:
|
||||
data = response.json()
|
||||
|
@ -99,7 +100,7 @@ def resolve_access_token(authorization_code, redirect_uri, logger):
|
|||
logger.warning(u'oauth2 error on access token retrieval: %r', response.content)
|
||||
return
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.error(u'unable to retrieve access token {}'.format(e))
|
||||
logger.warning(u'unable to retrieve access token {}'.format(e))
|
||||
else:
|
||||
try:
|
||||
response = response.json()
|
||||
|
@ -193,7 +194,7 @@ class FcOAuthSessionViewMixin(LoggerMixin):
|
|||
data = self.oauth_session().get(url, verify=verify, allow_redirects=False, timeout=3)
|
||||
data.raise_for_status()
|
||||
except requests.exceptions.RequestException as e:
|
||||
self.logger.error(u'unable to retrieve ressource from {} due to {}'.format(url, e))
|
||||
self.logger.warning(u'unable to retrieve ressource from {} due to {}'.format(url, e))
|
||||
else:
|
||||
try:
|
||||
data = data.json()
|
||||
|
@ -270,8 +271,9 @@ class FcOAuthSessionViewMixin(LoggerMixin):
|
|||
self.logger.debug('fc id_token %s', self.id_token)
|
||||
for key in self.id_token:
|
||||
setattr(self, key, self.id_token[key])
|
||||
self.oauth_session = lambda: OAuth2Session(
|
||||
app_settings.client_id, token=self.token)
|
||||
self.oauth_session = lambda: utils.requests_retry_session(
|
||||
session=OAuth2Session(
|
||||
app_settings.client_id, token=self.token))
|
||||
self.user_info = self.get_user_info()
|
||||
if not self.user_info:
|
||||
msg = 'userinfo resolution failed : {}'.format(self.token)
|
||||
|
|
Reference in New Issue