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

1"""Rate limit configuration for TipSharks API. 

2 

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""" 

6 

7from fastapi import Request 

8from slowapi.util import get_remote_address 

9 

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} 

19 

20 

21def get_user_rate_limit_key(request: Request) -> str: 

22 """Generate rate limit key from user ID header or IP address. 

23 

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. 

27 

28 Keys are namespaced (``user:`` / ``ip:``) to avoid accidental collisions. 

29 

30 Args: 

31 request: FastAPI incoming request. 

32 

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}" 

41 

42 # Fall back to IP-based key 

43 return f"ip:{get_remote_address(request)}"