Coverage for packages / core / common / rate_limit.py: 70%
10 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-05-08 08:14 +1200
« prev ^ index » next coverage.py v7.13.5, created at 2026-05-08 08:14 +1200
1"""Rate limit configuration for TipSharks API.
3Provides centralized rate limit definitions and a key function that supports
4per-user rate limiting via the X-User-ID header, with IP fallback for anonymous clients.
5"""
7from fastapi import Request
8from slowapi.util import get_remote_address
10# Default rate limits per endpoint group (applied per-user when user ID is available)
11RATE_LIMITS = {
12 "default": "100/minute",
13 "races_list": "200/minute",
14 "race_detail": "100/minute",
15 "predictions": "50/minute",
16 "export": "10/minute",
17 "admin": "20/minute",
18}
21def get_user_rate_limit_key(request: Request) -> str:
22 """Generate rate limit key from user ID header or IP address.
24 Uses the ``X-User-ID`` header for per-user rate limiting when the mobile
25 client provides an anonymous identifier. Falls back to the client IP
26 address for unauthenticated (e.g. browser) requests.
28 Keys are namespaced (``user:`` / ``ip:``) to avoid accidental collisions.
30 Args:
31 request: FastAPI incoming request.
33 Returns:
34 A string suitable for use as a slowapi rate-limit key.
35 """
36 user_id = request.headers.get("X-User-ID")
37 if user_id:
38 user_id = user_id.strip()
39 if user_id:
40 return f"user:{user_id}"
42 # Fall back to IP-based key
43 return f"ip:{get_remote_address(request)}"