|
| 1 | +from datetime import timedelta, datetime, timezone |
1 | 2 | from types import TracebackType
|
2 | 3 | from contextvars import ContextVar
|
3 | 4 | from contextlib import contextmanager, asynccontextmanager
|
|
22 | 23 | from .response import Response
|
23 | 24 | from .utils import obj_to_jsonable
|
24 | 25 | from .config import Config, get_config
|
25 |
| -from .exception import RequestError, RequestFailed, RequestTimeout |
| 26 | +from .exception import RequestError, RequestFailed, RequestTimeout, RateLimitExceededError |
26 | 27 | from .auth import BaseAuthStrategy, TokenAuthStrategy, UnauthAuthStrategy
|
27 | 28 | from .typing import (
|
28 | 29 | URLTypes,
|
@@ -316,6 +317,21 @@ def _check(
|
316 | 317 | if response.is_error:
|
317 | 318 | error_models = error_models or {}
|
318 | 319 | status_code = str(response.status_code)
|
| 320 | + |
| 321 | + if response.status_code == 403 and "retry-after" in response.headers: |
| 322 | + raise RateLimitExceededError(timedelta(seconds=int(response.headers["retry-after"])), original_message=response.content) |
| 323 | + |
| 324 | + if ( |
| 325 | + response.status_code in [403, 429] |
| 326 | + and "x-ratelimit-remaining" in response.headers |
| 327 | + and response.headers["x-ratelimit-remaining"] == "0" |
| 328 | + ): |
| 329 | + retry_after = datetime.fromtimestamp( |
| 330 | + int(response.headers["x-ratelimit-reset"]), tz=timezone.utc |
| 331 | + ) - datetime.now(tz=timezone.utc) |
| 332 | + retry_after = max(retry_after, timedelta()) |
| 333 | + raise RateLimitExceededError(retry_after, original_message=response.content) |
| 334 | + |
319 | 335 | error_model = error_models.get(
|
320 | 336 | status_code,
|
321 | 337 | error_models.get(
|
|
0 commit comments