Skip to content

Commit

Permalink
Update client to respect the newer RateLimit header (#115)
Browse files Browse the repository at this point in the history
* update test to target new header (currently failing)

* fix test

* bump version
  • Loading branch information
AlecRosenbaum authored Jul 25, 2023
1 parent 8dd7fa3 commit 48d1503
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 3 deletions.
15 changes: 14 additions & 1 deletion closeio_api/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import contextlib
import logging
import re
import time

from random import uniform
Expand All @@ -12,7 +13,7 @@

# To update the package version, change this variable. This variable is also
# read by setup.py when installing the package.
__version__ = '2.0'
__version__ = '2.1'

class APIError(Exception):
"""Raised when sending a request to the API failed."""
Expand Down Expand Up @@ -146,8 +147,20 @@ def _get_rate_limit_sleep_time(self, response):
"""Get rate limit window expiration time from response if the response
status code is 429.
"""
with contextlib.suppress(KeyError):
rate_limit = response.headers["RateLimit"]
# we don't actually need all these values, but per the RFC:
# "Malformed RateLimit header fields MUST be ignored."
match = re.match(
r"limit=(\d+), remaining=(\d+), reset=(\d+)", rate_limit
)
if match:
limit, remaining, reset = match.groups()
return float(reset)

with contextlib.suppress(KeyError):
return float(response.headers["Retry-After"])

with contextlib.suppress(KeyError):
return float(response.headers["RateLimit-Reset"])

Expand Down
17 changes: 15 additions & 2 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,20 @@ def request_callback(request):
assert resp['data'][0]['name'] == 'Sample Lead'

@responses.activate
def test_retry_on_rate_limit(api_client):
@pytest.mark.parametrize(
"headers",
[
{"RateLimit-Reset": "1"},
{"Retry-After": "1"},
{"RateLimit": "limit=100, remaining=0, reset=1"},
{
"Retry-After": "1",
"RateLimit-Reset": "1",
"RateLimit": "limit=100, remaining=0, reset=1",
},
]
)
def test_retry_on_rate_limit(api_client, headers):
with responses.RequestsMock() as rsps:

# Rate limit the first request and suggest it can be retried in 1 sec.
Expand All @@ -117,7 +130,7 @@ def test_retry_on_rate_limit(api_client):
body=json.dumps({}),
status=429,
content_type='application/json',
headers={"Retry-After": "1", "RateLimit-Reset": "1"}
headers=headers,
)

# Respond correctly to the second request.
Expand Down

0 comments on commit 48d1503

Please sign in to comment.