Files
Solo_bot/api/ratelimit.py
T
2026-04-23 00:30:12 +00:00

63 lines
1.8 KiB
Python

from __future__ import annotations
from fastapi import HTTPException, Request
from sqlalchemy.ext.asyncio import AsyncSession
from api.depends import _identity_from_cookie
async def enforce_rate_limit(
request: Request,
session: AsyncSession,
*,
bucket: str,
max_per_window: int,
window_sec: int,
identity_aware: bool = True,
) -> None:
try:
from api.v2.routes.auth._fallback_limiter import check_and_increment
from core.redis_cache import cache_incr_checked
except Exception:
return
owner = "anon"
if identity_aware:
try:
identity = await _identity_from_cookie(session, request)
if identity is not None and getattr(identity, "id", None):
owner = f"id:{identity.id}"
except Exception:
pass
if owner == "anon":
ip = (request.client.host if request.client else "") or "unknown"
owner = f"ip:{ip}"
key = f"rl:{bucket}:{owner}"
try:
count, redis_ok = await cache_incr_checked(key, window_sec)
if not redis_ok:
count = check_and_increment(key, max_per_window, window_sec)
except Exception:
return
if count > max_per_window:
raise HTTPException(status_code=429, detail="Слишком много запросов, подождите и попробуйте снова")
def rate_limit_dependency(*, bucket: str, max_per_window: int, window_sec: int):
from api.depends import get_session
from fastapi import Depends
async def _dep(request: Request, session: AsyncSession = Depends(get_session)) -> None:
await enforce_rate_limit(
request,
session,
bucket=bucket,
max_per_window=max_per_window,
window_sec=window_sec,
)
return _dep