Exercices Django Avancé Rate Limiter
🎉

Bravo!

Avancé 🧠 Fondamentaux 30 XP 0 personnes ont réussi

Rate Limiter

Sans rate limiting, un bot peut envoyer 10 000 requetes par seconde a ton API et la faire tomber. C'est aussi simple que ca. Le rate limiting est la premiere ligne de defense : il limite le nombre de requetes qu'un utilisateur peut faire dans un intervalle de temps donne. En cas de depassement, le serveur repond avec un status 429 (Too Many Requests).

C'est un mecanisme que tu retrouves partout : l'API GitHub te limite a 5000 requetes par heure, l'API OpenAI a un nombre de tokens par minute. Le principe est le meme. On va implementer un rate limiter base sur une fenetre glissante de temps.

Tu vas créer une classe RateLimiter qui :

__init__(max_requests, window_seconds) : configure le nombre maximum de requêtes autorisees dans une fenetre de temps

is_allowed(user_id, current_time) : vérifie si l'utilisateur a le droit de faire une requête au temps current_time. La méthode :
1. Nettoie les anciens timestamps (ceux qui sont en dehors de la fenetre)
2. Vérifie si le nombre de requêtes restantes ne dépasse pas max_requests
3. Si autorise, enregistre le timestamp et retourne {'allowed': True, 'remaining': nombre_restant}
4. Si refuse, retourne {'allowed': False, 'retry_after': secondes_avant_prochaine_fenetre}

get_usage(user_id, current_time) : retourne le nombre de requêtes dans la fenetre actuelle

Exemple :

rl = RateLimiter(max_requests=3, window_seconds=60)
rl.is_allowed('alice', 100.0) renvoie {'allowed': True, 'remaining': 2}
rl.is_allowed('alice', 101.0) renvoie {'allowed': True, 'remaining': 1}
rl.is_allowed('alice', 102.0) renvoie {'allowed': True, 'remaining': 0}
rl.is_allowed('alice', 103.0) renvoie {'allowed': False, 'retry_after': 57.0}

Tests (4/5)

Premières requêtes autorisees
rl = RateLimiter(max_requests=3, window_seconds=60)
r = rl.is_allowed('alice', 100.0)
assert r['allowed'] == True and r['remaining'] == 2
Depassement du seuil
rl = RateLimiter(max_requests=2, window_seconds=60)
rl.is_allowed('alice', 100.0)
rl.is_allowed('alice', 101.0)
r = rl.is_allowed('alice', 102.0)
assert r['allowed'] == False and 'retry_after' in r
Users independants
rl = RateLimiter(max_requests=1, window_seconds=60)
rl.is_allowed('alice', 100.0)
r_alice = rl.is_allowed('alice', 101.0)
r_bob = rl.is_allowed('bob', 101.0)
assert r_alice['allowed'] == False
assert r_bob['allowed'] == True
Fenetre glissante
rl = RateLimiter(max_requests=2, window_seconds=10)
rl.is_allowed('alice', 100.0)
rl.is_allowed('alice', 105.0)
r = rl.is_allowed('alice', 111.0)
assert r['allowed'] == True

+ 0 tests cachés

Indices (3 disponibles)

solution.py