From 0ab88caf400a77627b34c88943ce9686ba101a26 Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Sun, 11 Feb 2018 22:09:36 +0100 Subject: [PATCH 2/2] 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. --- src/authentic2_auth_fc/utils.py | 25 +++++++++++++++++++++++++ src/authentic2_auth_fc/views.py | 12 +++++++----- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/authentic2_auth_fc/utils.py b/src/authentic2_auth_fc/utils.py index f2ba2f7..98c5d7b 100644 --- a/src/authentic2_auth_fc/utils.py +++ b/src/authentic2_auth_fc/utils.py @@ -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 diff --git a/src/authentic2_auth_fc/views.py b/src/authentic2_auth_fc/views.py index 80e1afa..85aa506 100644 --- a/src/authentic2_auth_fc/views.py +++ b/src/authentic2_auth_fc/views.py @@ -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() @@ -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) -- 2.14.2