Skip to content

Commit 683529d

Browse files
committed
fix: handle broken rate limit as best effort (#126)
1 parent a63992f commit 683529d

File tree

2 files changed

+52
-3
lines changed

2 files changed

+52
-3
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from datetime import datetime, timezone
2+
3+
from stream_chat.types.stream_response import StreamResponse
4+
5+
6+
class TestResponse:
7+
def test_clean_header(self):
8+
headers = {
9+
"x-ratelimit-limit": "300",
10+
"x-ratelimit-remaining": "299",
11+
"x-ratelimit-reset": "1598806800",
12+
}
13+
response = StreamResponse({}, headers, 200)
14+
assert response.rate_limit().limit == 300
15+
assert response.rate_limit().remaining == 299
16+
assert response.rate_limit().reset == datetime.fromtimestamp(
17+
1598806800, timezone.utc
18+
)
19+
20+
headers_2 = {
21+
"x-ratelimit-limit": "300, 300",
22+
"x-ratelimit-remaining": "299, 299",
23+
"x-ratelimit-reset": "1598806800, 1598806800",
24+
}
25+
response = StreamResponse({}, headers_2, 200)
26+
assert response.rate_limit().limit == 300
27+
assert response.rate_limit().remaining == 299
28+
assert response.rate_limit().reset == datetime.fromtimestamp(
29+
1598806800, timezone.utc
30+
)
31+
32+
headers_3 = {
33+
"x-ratelimit-limit": "garbage",
34+
"x-ratelimit-remaining": "garbage",
35+
"x-ratelimit-reset": "garbage",
36+
}
37+
response = StreamResponse({}, headers_3, 200)
38+
assert response.rate_limit().limit == 0
39+
assert response.rate_limit().remaining == 0
40+
assert response.rate_limit().reset == datetime.fromtimestamp(0, timezone.utc)

stream_chat/types/stream_response.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,22 @@ def __init__(
3838
)
3939
if limit and remaining and reset:
4040
self.__rate_limit = RateLimitInfo(
41-
limit=int(limit),
42-
remaining=int(remaining),
43-
reset=datetime.fromtimestamp(float(reset), timezone.utc),
41+
limit=int(self._clean_header(limit)),
42+
remaining=int(self._clean_header(remaining)),
43+
reset=datetime.fromtimestamp(
44+
float(self._clean_header(reset)), timezone.utc
45+
),
4446
)
4547

4648
super(StreamResponse, self).__init__(response_dict)
4749

50+
def _clean_header(self, header: str) -> int:
51+
try:
52+
values = (v.strip() for v in header.split(","))
53+
return int(next(v for v in values if v))
54+
except ValueError:
55+
return 0
56+
4857
def rate_limit(self) -> Optional[RateLimitInfo]:
4958
"""Returns the ratelimit info of your API operation."""
5059
return self.__rate_limit

0 commit comments

Comments
 (0)