"""Simple in-memory rate limiter per user.""" from __future__ import annotations import time from collections import defaultdict from typing import Annotated from fastapi import Depends, HTTPException, status from app.api.deps import require_student from app.core.schemas import UserProfile class RateLimiter: def __init__(self, max_requests: int, window_seconds: int) -> None: self._max = max_requests self._window = window_seconds self._buckets: dict[int, list[float]] = defaultdict(list) def check(self, user_id: int) -> None: now = time.time() cutoff = now - self._window bucket = self._buckets[user_id] # purge expired entries while bucket and bucket[0] < cutoff: bucket.pop(0) if len(bucket) >= self._max: raise HTTPException( status_code=status.HTTP_429_TOO_MANY_REQUESTS, detail=f"请求过于频繁,请 {self._window // 60} 分钟后重试", ) bucket.append(now) _diagnosis_limiter = RateLimiter(max_requests=5, window_seconds=60) def check_diagnosis_rate_limit( user: Annotated[UserProfile, Depends(require_student)], ) -> None: _diagnosis_limiter.check(user.id)