Neda/Back/core/rate_limit.py
2026-03-28 15:37:02 +03:30

39 lines
1.4 KiB
Python

# core/rate_limit.py
from fastapi import Request, HTTPException, status
from db.redis import redis_client
class RateLimiter:
def __init__(self, requests: int, window_seconds: int, scope: str = "global"):
"""
:param requests: number of requests allowed
:param window_seconds: window time in seconds
:param scope: type of limit ("global" for all site, "endpoint" for a specific path)
"""
self.requests = requests
self.window_seconds = window_seconds
self.scope = scope
async def __call__(self, request: Request):
client_ip = request.client.host if request.client else "127.0.0.1"
real_ip = request.headers.get("x-real-ip", request.headers.get("x-forwarded-for", client_ip))
real_ip = real_ip.split(",")[0].strip()
if self.scope == "global":
key = f"rate_limit:global:{real_ip}"
else:
path = request.scope["path"]
key = f"rate_limit:endpoint:{real_ip}:{path}"
current_count = await redis_client.incr(key)
if current_count == 1:
await redis_client.expire(key, self.window_seconds)
if current_count > self.requests:
await redis_client.expire(key, self.window_seconds)
raise HTTPException(
status_code=status.HTTP_429_TOO_MANY_REQUESTS,
detail="Too many requests. Please try again later."
)