Limitation du débit
Les manettes @bext-stack/framework/rate-limit demandent la méthode Laravel RateLimiter : une fenêtre fixe par clé, avec check / attempt / peek / reset et un résultat portant allowed, remaining et retryAfterSecs.
Quand l'utiliser#
- Protégez une action de connexion, d’inscription ou de réinitialisation de mot de passe contre la force brute.
- Limitez un point de terminaison coûteux ou abusif par client/par utilisateur.
- Toute règle "N par fenêtre".
Garder une action#
import { createRateLimiter, memoryRateStore, keyForRequest } from "@bext-stack/framework/rate-limit";
const limiter = createRateLimiter({ store: memoryRateStore() });
export async function action({ request }) {
const key = keyForRequest(request, "login"); // client IP + bucket
const r = await limiter.check(key, { max: 5, windowSecs: 60 });
if (!r.allowed) {
return new Response("Too many requests", {
status: 429,
headers: { "retry-after": String(r.retryAfterSecs) },
});
}
// …authenticate…
if (loginSucceeded) await limiter.reset(key); // clear on success
}
check enregistre une réponse positive et rend compte du verdict. attempt(key, opts, fn) fonctionne
fn uniquement lorsqu'il est inférieur à la limite et renvoie le résultat avec l'état :
const out = await limiter.attempt(key, { max: 5, windowSecs: 60 }, () => sendCode());
if (!out.allowed) { /* throttled — out.retryAfterSecs */ }
| Membre | Fait |
|---|---|
check(key, { max, windowSecs }) |
enregistrer un hit → RateLimitResult |
peek(key, opts) |
l'état sans que ne consomme de hit |
attempt(key, opts, fn) |
exécutez fn uniquement si cela est autorisé ; le résultat entraîne le résultat |
reset(key) |
effacer la fenêtre d'une clé |
keyForRequest(request, bucket?) |
"<bucket>:<client-ip>" à partir des en-têtes proxy |
RateLimitResult: { allowed, limit, remaining, retryAfterSecs, resetAt }.
Stockages#
Le limiteur est une fine couche sur un RateLimitStore :
memoryRateStore()— fenêtre fixe en cours de processus. Par-V8-isolat - bien pour un travailleur unique et tests.- Apportez le vôtre (implémentez
hit/peek/reset) soutenu par un magasin partagé pour limite sur une flotte de travailleurs.
Utilisez keyForRequest(request, "signup") pour que différentes actions soient limitées indépendamment et préférez un magasin** partagé **en production : un magasin de mémoire par isolement limite chaque travailleur séparément, de sorte que la limite effective est max × workers.
Essayez-le#
Le démo à limitation de débit en direct déclenche une rafale de 6 requêtes avec une limite de 3 — les trois premières passes, les autres sont bloquées avec une nouvelle tentative après. Source dans sites/demo/src/app/examples/rate-limit/page.tsx.
Voir aussi#
- Sécurité — autres mesures de durcissement des demandes.
- Authentification — le flux de connexion à protéger.
- Boîte à outils de candidature — le reste de la couche d'application TypeScript.