X

Limitation du débit de l’API dans Laravel 5.2


De plus en plus de mon travail à Laravel ces derniers temps a été de créer des API. J’ai une classe de limiteur de débit manuel que j’utilise, mais j’ai eu le sentiment qu’il existe une façon plus propre de le faire. Sans surprise, lorsque Taylor a entrepris d’écrire un middleware limiteur de débit pour Laravel, il l’a fait plus proprement et mieux que moi.

Brève introduction à la limitation de débit

Si vous ne le connaissez pas, la limitation de débit est un outil, le plus souvent utilisé dans les API, qui limites le taux auquel tout demandeur individuel peut faire des demandes.

Cela signifie, par exemple, que si un bot atteint mille fois par minute une route d’API particulièrement coûteuse, votre application ne plantera pas, car après le nième essayez, ils obtiendront plutôt un 429: Too Many Attempts. réponse du serveur.

Habituellement, une application bien écrite qui implémente la limitation de débit retransmettra également trois en-têtes qui pourraient ne pas être sur une autre application : X-RateLimit-Limit, X-RateLimit-Remaininget Retry-After (vous n’obtiendrez que Retry-After si vous avez atteint la limite). X-RateLimit-Limit vous indique le nombre maximum de requêtes que vous êtes autorisé à faire pendant la période de cette application, X-RateLimit-Remaining vous indique le nombre de demandes qu’il vous reste dans cette période actuelle, et Retry-After vous indique combien de secondes attendre avant de réessayer. (Retry-After peut également être une date au lieu d’un nombre de secondes).

Remarque : Chaque API choisit la période pour laquelle elle limite le débit. GitHub est par heure, Twitter est par segment de 15 minutes. Ce middleware Laravel est à la minute.

Comment utiliser le middleware de limitation de débit de Laravel

Passons donc à la nouvelle fonctionnalité de Laravel 5.2. Il y a un nouveau throttle middleware que vous pouvez utiliser. Jetons un coup d’œil à notre groupe d’API :

Route::group(['prefix' => 'api'], function () {
    Route::get('people', function () {
        return Person::all();
    });
});

Appliquons-y un accélérateur. L’accélérateur par défaut le limite à 60 tentatives par minute et désactive leur accès pendant une seule minute s’ils atteignent la limite.

Route::group(['prefix' => 'api', 'middleware' => 'throttle'], function () {
    Route::get('people', function () {
        return Person::all();
    });
});

Si vous faites une demande à ce api/people route, vous verrez maintenant les lignes suivantes dans les en-têtes de réponse :

HTTP/1.1 200 OK
... other headers here ...
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59

N’oubliez pas que cette réponse signifie :

A) Cette requête a réussi (le statut est 200)
B) Vous pouvez essayer cet itinéraire 60 fois par minute
C) Il vous reste 59 requêtes pour cette minute

Quelle réponse obtiendrions-nous si nous dépassions la limite de taux ?

HTTP/1.1 429 Too Many Requests
... other headers here ...
Retry-After: 60
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0

Et le contenu réel de la réponse serait une chaîne : “Trop de tentatives”.

Et si on réessayait après 30 secondes ?

HTTP/1.1 429 Too Many Requests
... other headers here ...
Retry-After: 30
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0

Même réponse, sauf le Retry-After la minuterie qui nous indique combien de temps attendre a diminué de 30 secondes.

Personnaliser le throttle middleware

Faisons un peu de personnalisation. Nous voulons le limiter à 5 tentatives par minute.

Route::group(['prefix' => 'api', 'middleware' => 'throttle:5'], function () {
    Route::get('people', function () {
        return Person::all();
    });
});

Et si nous voulons le changer pour que, si quelqu’un atteint la limite, il ne puisse pas réessayer avant 10 minutes ?

Route::group(['prefix' => 'api', 'middleware' => 'throttle:5,10'], function () {
    Route::get('people', function () {
        return Person::all();
    });
});

C’est tout ce qu’on peut en dire!

Vous pouvez voir le code qui prend en charge ceci ici : ThrottlesRequests.php