Version de développement
Cette documentation décrit la version « next » (develop), non encore publiée. Pour la version stable, basculez sur « v5 » dans l'en-tête.
API

Décorateur @rate_limit

Limiter le nombre d'appels à une fonction ou une route API avec le décorateur @rate_limit de Dodock

Décorateur @rate_limit

Le décorateur rate_limit limite le nombre d'appels à une méthode pendant une période. Au-delà de la limite, Dodock lève frappe.RateLimitExceededError et la réponse HTTP a le code 429.

Le décorateur agit seulement pendant une requête HTTP. Un appel depuis une tâche de fond ou la console n'est pas compté.

Principe

Dodock garde un compteur dans Redis pour chaque méthode et chaque identité. Le compteur expire à la fin de la période (seconds).

Paramètres

from frappe.rate_limiter import rate_limit
ParamètreDéfautRôle
limit5Nombre maximal d'appels dans la période. Accepte une fonction qui renvoie un entier
seconds86400 (24 h)Durée de la période, en secondes
methods"ALL"Méthodes HTTP comptées, par exemple ["POST"]. "ALL" compte toutes les méthodes
ip_basedTrueIdentifie l'appelant par son adresse IP
keyNoneNom d'un paramètre de la requête. Sa valeur est ajoutée à l'identité, par exemple l'adresse e-mail saisie
user_basedFalseIdentifie l'appelant par son utilisateur connecté
endpointChemin de la fonctionNom du compteur. Nécessaire si la fonction n'a pas de chemin pointé stable, par exemple un functools.partial

Identité de l'appelant

RéglageIdentité
Par défaut (ip_based=True)Adresse IP, plus la valeur du paramètre key si key est défini
ip_based=False et key définiValeur du paramètre key seulement
user_based=TrueUtilisateur connecté. Pour un invité, adresse IP. Plus la valeur du paramètre key si key est défini

Pourquoi suivre par utilisateur

Dans une entreprise, plusieurs personnes partagent souvent la même adresse IP publique. Avec un suivi par IP, une personne qui atteint la limite bloque aussi ses collègues. Avec user_based=True, chaque utilisateur connecté a son propre compteur.

Exemples

Limite par utilisateur

import frappe
from frappe.rate_limiter import rate_limit


@frappe.whitelist()
@rate_limit(limit=20, seconds=60, user_based=True)
def rechercher_clients(search_term: str):
    """Chaque utilisateur peut faire 20 recherches par minute."""
    return frappe.get_list(
        "Customer",
        filters={"customer_name": ["like", f"%{search_term}%"]},
        fields=["name", "customer_name"],
        limit=50,
    )

Deux utilisateurs derrière la même adresse IP ont chacun 20 recherches par minute.

Limite par IP et par paramètre, sur les seuls appels POST

@frappe.whitelist(allow_guest=True)
@rate_limit(key="email", limit=5, seconds=60 * 60, methods=["POST"])
def demander_rappel(email: str):
    ...

Chaque couple adresse IP et adresse e-mail peut envoyer 5 demandes par heure.

Limite dynamique

limit accepte une fonction. Dodock l'appelle à chaque requête.

@frappe.whitelist()
@rate_limit(
    limit=lambda: frappe.db.get_single_value("Mes Parametres", "limite_appels"),  # type de document fictif
    seconds=300,
    user_based=True,
)
def mon_point_acces():
    ...

Bonnes pratiques

  • Placez @frappe.whitelist() au-dessus de @rate_limit(...).
  • Utilisez user_based=True pour les méthodes réservées aux utilisateurs connectés.
  • Pour une méthode ouverte aux invités, gardez le suivi par IP et ajoutez key si un identifiant est saisi.
  • Choisissez un seuil adapté à l'usage réel. Trop bas, il bloque le travail normal. Trop haut, il ne protège plus.