Rate Limiting dans Node.js : Guide complet pour protéger les API et gérer la charge

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Rate Limiting dans Node.js : Protéger les API contre les surcharges et les attaquants

\n\n

Le rate limiting (limitation du taux de requêtes) est un mécanisme essentiel pour toute application web Node.js. Il permet de contrôler le nombre de requêtes qu'un client peut envoyer au serveur sur une période donnée. Sans rate limiting, votre API est vulnérable aux attaques DDoS, aux surcharges accidentelles et à la consommation excessive de ressources.

\n\n

Pourquoi le Rate Limiting est-il nécessaire ?

\n
    \n
  • Protection contre le brute force : Empêche les tentatives de connexion répétées.
  • \n
  • Prévention des DDoS : Limite l'impact des attaques par déni de service.
  • \n
  • Répartition équitable des ressources : Garantit un accès égal pour tous les utilisateurs.
  • \n
  • Économies de coûts : Réduit la charge sur les serveurs et les bases de données.
  • \n
  • Conformité aux SLA : Respect des accords de niveau de service.
  • \n
\n\n

Algorithmes principaux de Rate Limiting

\n

Il existe plusieurs approches pour implémenter la limitation de débit. Voici les plus courantes :

\n\n

1. Sliding Window (Fenêtre glissante)

\n

L'algorithme le plus répandu. Les requêtes sont regroupées dans des fenêtres temporelles (ex. 1 minute). Si le nombre de requêtes dépasse la limite, les requêtes suivantes sont rejetées jusqu'au début d'une nouvelle fenêtre.

\n\n

2. Token Bucket (Seau de jetons)

\n

Un "seau" virtuel contient des jetons. Chaque requête consomme un jeton. Les jetons sont renouvelés à une vitesse fixe. Si le seau est vide, la requête est rejetée.

\n\n

3. Leaky Bucket (Seau percé)

\n

Les requêtes entrent dans une file d'attente et sont traitées à une vitesse constante. Si la file d'attente est pleine, les requêtes sont abandonnées.

\n\n

Bibliothèques pour le Rate Limiting dans Node.js

\n\n

1. express-rate-limit

\n

La bibliothèque la plus populaire pour Express.js. Simple à utiliser et personnalisable.

\n\n
const rateLimit = require('express-rate-limit');\n\n// Créer un middleware pour limiter les requêtes\nconst limiter = rateLimit({\n  windowMs: 15 * 60 * 1000, // 15 minutes\n  max: 100, // maximum 100 requêtes par fenêtre\n  message: 'Trop de requêtes, veuillez réessayer plus tard.',\n  standardHeaders: true, // Retourne les en-têtes RateLimit-*\n  legacyHeaders: false, // Désactive les en-têtes X-RateLimit-*\n});\n\n// Appliquer à toutes les routes\napp.use(limiter);\n\n// Ou seulement à une route spécifique\napp.use('/api/login', limiter);\n
\n\n

2. bottleneck

\n

Bibliothèque universelle fonctionnant avec toutes les opérations asynchrones. Prend en charge les algorithmes Token Bucket et Leaky Bucket.

\n\n
const Bottleneck = require('bottleneck');\n\n// Créer un limiteur : 5 requêtes par seconde\nconst limiter = new Bottleneck({\n  minTime: 200, // 200 ms entre les requêtes\n  maxConcurrent: 5, // maximum 5 requêtes simultanées\n  reservoir: 100, // nombre initial de jetons\n  reservoirRefreshAmount: 100,\n  reservoirRefreshInterval: 60 * 1000, // renouvellement toutes les minutes\n});\n\n// Envelopper une fonction dans le limiteur\nasync function fetchData(url) {\n  const response = await fetch(url);\n  return response.json();\n}\n\nconst limitedFetch = limiter.wrap(fetchData);\n\n// Utilisation\nconst data = await limitedFetch('https://api.example.com/data');\n
\n\n

3. rate-limiter-flexible

\n

Bibliothèque flexible avec prise en charge de Redis, MongoDB, Memcached et d'autres stockages. Idéale pour les systèmes distribués.

\n\n
const { RateLimiterRedis } = require('rate-limiter-flexible');\nconst Redis = require('ioredis');\n\nconst redisClient = new Redis();\n\nconst rateLimiter = new RateLimiterRedis({\n  storeClient: redisClient,\n  keyPrefix: 'middleware',\n  points: 10, // 10 requêtes\n  duration: 1, // par 1 seconde\n});\n\napp.use(async (req, res, next) => {\n  try {\n    await rateLimiter.consume(req.ip);\n    next();\n  } catch (rejRes) {\n    res.status(429).send('Trop de requêtes');\n  }\n});\n

Recommendations