Skip to content

Commit ba8cc17

Browse files
committed
fix: remove infinite recursion for HTTP 401 errors 🪲
1 parent c6d701f commit ba8cc17

1 file changed

Lines changed: 34 additions & 14 deletions

File tree

src/client/client.py

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ class OneDriveClientException(Exception):
1616
pass
1717

1818

19+
class OneDriveTransientException(OneDriveClientException):
20+
"""Raised for transient HTTP errors (429, 5xx) that are safe to retry."""
21+
pass
22+
23+
1924
class OneDriveClient(HttpClient):
2025
"""
2126
The OneDriveClient class manages the interaction with OneDrive API. It handles tasks such as
@@ -138,19 +143,34 @@ def refresh_token(self):
138143
return self._refresh_token
139144

140145
def get_request(self, url: str, is_absolute_path: bool, stream: bool = False):
141-
response = self.get_raw(url, is_absolute_path=is_absolute_path, stream=stream)
142-
if response.status_code == 200:
143-
return response
144-
elif response.status_code == 401:
145-
self._get_request_tokens()
146-
return self.get_request(url, is_absolute_path, stream)
147-
elif response.status_code == 404:
148-
logging.error(f"Url {url} returned 404.")
149-
return None
150-
else:
151-
raise OneDriveClientException(f"Cannot fetch {url}, "
152-
f"response: {response.text}, "
153-
f"status_code: {response.status_code}")
146+
for attempt in range(2):
147+
response = self.get_raw(url, is_absolute_path=is_absolute_path, stream=stream)
148+
if response.status_code == 200:
149+
return response
150+
elif response.status_code == 404:
151+
logging.error(f"Url {url} returned 404.")
152+
return None
153+
elif response.status_code == 401:
154+
if attempt == 0:
155+
logging.warning(f"Got 401 fetching {url}, refreshing token and retrying...")
156+
self._get_request_tokens()
157+
continue
158+
error_body = response.json()
159+
error_code = error_body.get("error", "unknown")
160+
error_desc = error_body.get("error_description", "no description")
161+
raise OneDriveClientException(
162+
f"Authentication failed after token refresh (HTTP 401): "
163+
f"{error_code} - {error_desc}"
164+
)
165+
elif response.status_code in (429, 500, 502, 503, 504):
166+
raise OneDriveTransientException(
167+
f"Transient error fetching {url}: HTTP {response.status_code} - {response.text}"
168+
)
169+
else:
170+
raise OneDriveClientException(
171+
f"Cannot fetch {url}, response: {response.text}, "
172+
f"status_code: {response.status_code}"
173+
)
154174

155175
def _resolve_folder_id(self, drive_type: str, folder_path: str):
156176
if folder_path is None or folder_path == '/':
@@ -302,7 +322,7 @@ def _get_sharepoint_document_libraries(self):
302322
raise OneDriveClientException(f"Error occurred when getting SharePoint document libraries:"
303323
f" {response.status_code}, {response.text}")
304324

305-
@backoff.on_exception(backoff.expo, Exception, max_tries=MAX_RETRIES)
325+
@backoff.on_exception(backoff.expo, OneDriveTransientException, max_tries=MAX_RETRIES)
306326
def _download_file_from_onedrive_url(self, url, output_path, filename):
307327
"""
308328
Downloads a file from OneDrive using the provided download URL and saves it to the specified output path.

0 commit comments

Comments
 (0)