Projet

Général

Profil

0002-retry-HTTP-requests-3-times-fixes-21783.patch

Benjamin Dauvergne, 11 février 2018 22:21

Télécharger (4,49 ko)

Voir les différences:

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.

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).
 src/authentic2_auth_fc/utils.py | 25 +++++++++++++++++++++++++
 src/authentic2_auth_fc/views.py | 16 +++++++++-------
 2 files changed, 34 insertions(+), 7 deletions(-)
src/authentic2_auth_fc/utils.py
5 5
import datetime
6 6
import uuid
7 7

  
8
import requests
9
from requests.adapters import HTTPAdapter
10
from requests.packages.urllib3.util.retry import Retry
11

  
8 12
from django.core.urlresolvers import reverse
9 13
from django.conf import settings
10 14
from django.shortcuts import resolve_url
......
158 162
            tags.add(mapping['tag'])
159 163
    if save_user:
160 164
        user.save()
165

  
166

  
167
def requests_retry_session(
168
    retries=3,
169
    backoff_factor=0.5,
170
    status_forcelist=(500, 502, 504),
171
    session=None,
172
):
173
    '''Create a requests session which retries  after 0.5s then 1s'''
174
    session = session or requests.Session()
175
    retry = Retry(
176
        total=retries,
177
        read=retries,
178
        connect=retries,
179
        backoff_factor=backoff_factor,
180
        status_forcelist=status_forcelist,
181
    )
182
    adapter = HTTPAdapter(max_retries=retry)
183
    session.mount('http://', adapter)
184
    session.mount('https://', adapter)
185
    return session
src/authentic2_auth_fc/views.py
1 1
import uuid
2
import requests
3 2
import logging
4 3
import json
5 4
import urlparse
6 5
import urllib
6
import requests
7 7

  
8 8
from requests_oauthlib import OAuth2Session
9 9

  
......
86 86
    }
87 87
    logger.debug('access token request %s', data)
88 88
    try:
89
        response = requests.post(
89
        session = utils.requests_retry_session()
90
        response = session.post(
90 91
            app_settings.token_url, data=data,
91 92
            verify=app_settings.verify_certificate,
92
            allow_redirects=False, timeout=10)
93
            allow_redirects=False, timeout=3)
93 94
        if response.status_code != 200:
94 95
            try:
95 96
                data = response.json()
......
99 100
                logger.warning(u'oauth2 error on access token retrieval: %r', response.content)
100 101
            return
101 102
    except requests.exceptions.RequestException as e:
102
        logger.error(u'unable to retrieve access token {}'.format(e))
103
        logger.warning(u'unable to retrieve access token {}'.format(e))
103 104
    else:
104 105
        try:
105 106
            response = response.json()
......
193 194
            data = self.oauth_session().get(url, verify=verify, allow_redirects=False, timeout=3)
194 195
            data.raise_for_status()
195 196
        except requests.exceptions.RequestException as e:
196
            self.logger.error(u'unable to retrieve ressource from {} due to {}'.format(url, e))
197
            self.logger.warning(u'unable to retrieve ressource from {} due to {}'.format(url, e))
197 198
        else:
198 199
            try:
199 200
                data = data.json()
......
270 271
            self.logger.debug('fc id_token %s', self.id_token)
271 272
            for key in self.id_token:
272 273
                setattr(self, key, self.id_token[key])
273
            self.oauth_session = lambda: OAuth2Session(
274
                app_settings.client_id, token=self.token)
274
            self.oauth_session = lambda: utils.requests_retry_session(
275
                session=OAuth2Session(
276
                    app_settings.client_id, token=self.token))
275 277
            self.user_info = self.get_user_info()
276 278
            if not self.user_info:
277 279
                msg = 'userinfo resolution failed : {}'.format(self.token)
278
-