@@ -206,9 +206,14 @@ class EclipseFoundationAPIClient:
206206 ECLIPSE_API_URL = "https://api.eclipse.org"
207207 ECLIPSE_ACCOUNTS_URL = "https://accounts.eclipse.org"
208208 OAUTH_TOKEN_ENDPOINT = "https://accounts.eclipse.org/oauth2/token"
209+ ECLIPSE_SCOPE = "eclipsefdn_view_all_profiles"
210+
211+ MAX_RETRIES = 3
209212
210213 def __init__ (self ):
211214 self .token = None
215+ self .user_id = None
216+ self .password = None
212217
213218 def login (self , user_id , password ):
214219 """Login on the Eclipse platform.
@@ -217,10 +222,12 @@ def login(self, user_id, password):
217222 "eclipsefdn_view_all_profiles" that will allow us to
218223 fetch all the info about profiles/identities.
219224 """
225+ self .user_id = user_id
226+ self .password = password
220227 self .token = self ._authenticate (
221- user_id ,
222- password ,
223- "eclipsefdn_view_all_profiles" ,
228+ self . user_id ,
229+ self . password ,
230+ self . ECLIPSE_SCOPE ,
224231 )
225232
226233 def logout (self ):
@@ -281,8 +288,7 @@ def _fetch(self, url, params=None):
281288 """Generic query to Eclipse usr API."""
282289
283290 try :
284- response = requests .get (url , params = params , auth = self .token )
285- response .raise_for_status ()
291+ data = self ._fetch_retry (url , params )
286292 except requests .exceptions .HTTPError as error :
287293 # Ignore 5xx errors
288294 if 500 <= error .response .status_code < 600 :
@@ -296,7 +302,41 @@ def _fetch(self, url, params=None):
296302 else :
297303 raise error
298304
299- return response .json ()
305+ return data
306+
307+ def _fetch_retry (self , url , params = None ):
308+ """Fetch URL retrying in case of 403 or 500 errors.
309+
310+ When getting a 403 error, the method will try to authenticate
311+ again in case the OAuth2 token has expired.
312+ """
313+ retries = 0
314+ max_retries = self .MAX_RETRIES
315+
316+ while retries < max_retries :
317+ response = requests .get (url , params = params , auth = self .token )
318+
319+ if response .status_code == 200 :
320+ return response .json ()
321+ elif response .status_code == 403 :
322+ # Refresh token if needed and try again
323+ if self .token .expires_at <= datetime_utcnow ():
324+ self .token = self ._authenticate (
325+ self .user_id ,
326+ self .password ,
327+ self .ECLIPSE_SCOPE ,
328+ )
329+ retries += 1
330+ elif 500 <= response .status_code < 600 :
331+ # Errors could have been related to server overloading
332+ retries += 1
333+ else :
334+ response .raise_for_status ()
335+
336+ response = requests .get (url , params = params , auth = self .token )
337+ response .raise_for_status ()
338+
339+ return response
300340
301341 def _authenticate (self , client_id , client_secret , scope ):
302342 """Authenticate using OAuth2.
0 commit comments