Pulled the per-IP sliding-window check out of auth_routes so the upcoming /profile/password endpoint can share it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
23 lines
613 B
Python
23 lines
613 B
Python
import time
|
|
|
|
|
|
def check_rate_limit(
|
|
bucket: dict[str, list[float]],
|
|
remote_addr: str,
|
|
*,
|
|
window: float,
|
|
max_attempts: int,
|
|
) -> bool:
|
|
"""Return True if this request should be rate-limited (rejected).
|
|
|
|
The bucket is owned by the caller so each endpoint can keep an
|
|
independent count and tests can reset state cleanly.
|
|
"""
|
|
now = time.time()
|
|
attempts = bucket.setdefault(remote_addr, [])
|
|
cutoff = now - window
|
|
attempts[:] = [ts for ts in attempts if ts >= cutoff]
|
|
if len(attempts) >= max_attempts:
|
|
return True
|
|
attempts.append(now)
|
|
return False
|