Skip to content

Commit d4c2fb6

Browse files
committed
Refactor and change default retry-after delay to 60 seconds
1 parent f81018b commit d4c2fb6

File tree

1 file changed

+15
-11
lines changed

1 file changed

+15
-11
lines changed

msal/throttled_http_client.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,27 +13,31 @@ def _hash(raw):
1313
return sha256(repr(raw).encode("utf-8")).hexdigest()
1414

1515

16-
def _handle_http_429_5xx_retry_after(result=None, **ignored):
16+
def _parse_http_429_5xx_retry_after(result=None, **ignored):
17+
"""Return seconds to throttle"""
1718
assert result is not None, """
1819
The signature defines it with a default value None,
1920
only because the its shape is already decided by the
2021
IndividualCache's.__call__().
2122
In actual code path, the result parameter here won't be None.
2223
"""
2324
response = result
24-
lowercase_headers = { # MSAL's HttpClient may not have headers
25-
k.lower(): v for k, v in getattr(response, "headers", {}).items()}
26-
default = 600
25+
lowercase_headers = {k.lower(): v for k, v in getattr(
26+
# Historically, MSAL's HttpResponse does not always have headers
27+
response, "headers", {}).items()}
28+
if not (response.status_code == 429 or response.status_code >= 500
29+
or "retry-after" in lowercase_headers):
30+
return 0 # Quick exit
31+
default = 60 # Recommended at the end of
32+
# https://identitydivision.visualstudio.com/devex/_git/AuthLibrariesApiReview?version=GBdev&path=%2FService%20protection%2FIntial%20set%20of%20protection%20measures.md&_a=preview
33+
retry_after = int(lowercase_headers.get("retry-after", default))
2734
try:
2835
# AAD's retry_after uses integer format only
2936
# https://stackoverflow.microsoft.com/questions/264931/264932
30-
retry_after = int(lowercase_headers.get("retry-after", default))
37+
delay_seconds = int(retry_after)
3138
except ValueError:
32-
retry_after = default
33-
return min(3600, retry_after) if (
34-
response.status_code == 429 or response.status_code >= 500
35-
or "retry-after" in lowercase_headers
36-
) else 0
39+
delay_seconds = default
40+
return min(3600, delay_seconds)
3741

3842

3943
def _extract_data(kwargs, key, default=None):
@@ -73,7 +77,7 @@ def __init__(self, http_client, http_cache):
7377
_extract_data(kwargs, "code", # "account" of auth code grant
7478
_extract_data(kwargs, "username")))), # "account" of ROPC
7579
),
76-
expires_in=_handle_http_429_5xx_retry_after,
80+
expires_in=_parse_http_429_5xx_retry_after,
7781
)(_post)
7882

7983
_post = IndividualCache( # It covers the "UI required cache"

0 commit comments

Comments
 (0)