29 lines
949 B
Python
29 lines
949 B
Python
"""Configuration and error carrier for per-user HTTP rate limiting."""
|
|
|
|
from dataclasses import dataclass
|
|
|
|
from app.core.config import Settings
|
|
from app.core.errors import RateLimitedError
|
|
|
|
|
|
class RateLimitExceededError(RateLimitedError):
|
|
def __init__(self, message: str, retry_after_seconds: int) -> None:
|
|
super().__init__(message)
|
|
self.retry_after_seconds = max(1, int(retry_after_seconds))
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class RateLimitPolicy:
|
|
enabled: bool
|
|
window_seconds: int
|
|
max_requests: int
|
|
key_prefix: str
|
|
|
|
@classmethod
|
|
def from_settings(cls, settings: Settings) -> "RateLimitPolicy":
|
|
return cls(settings.rate_limit_enabled, settings.rate_limit_window_seconds,
|
|
settings.rate_limit_max_requests, settings.rate_limit_key_prefix)
|
|
|
|
def key(self, user_id: str, method: str, route_path: str) -> str:
|
|
return f"{self.key_prefix}:{user_id}:{method.upper()}:{route_path}"
|