Limitación de tasa
Introducción
Laravel incluye una abstracción de limitación de tasa fácil de usar que, en combinación con la caché de tu aplicación, proporciona una manera sencilla de limitar cualquier acción durante un período de tiempo específico.
[!NOTA] Si estás interesado en limitar la tasa de solicitudes HTTP entrantes, consulta la documentación del middleware de limitador de tasa.
Configuración de Caché
Típicamente, el limitador de tasa utiliza la caché de aplicación predeterminada que se define por la clave default
dentro del archivo de configuración cache
de tu aplicación. Sin embargo, puedes especificar qué driver de caché debe usar el limitador de tasa definiendo una clave limiter
dentro del archivo de configuración cache
de tu aplicación:
'default' => env('CACHE_STORE', 'database'), 'limiter' => 'redis',
Uso Básico
La fachada Illuminate\Support\Facades\RateLimiter
puede utilizarse para interactuar con el limitador de velocidad. El método más simple que ofrece el limitador de velocidad es el método attempt
, que limita la tasa de un callback dado durante un número dado de segundos.
El método attempt
devuelve false
cuando el callback no tiene intentos restantes disponibles; de lo contrario, el método attempt
devolverá el resultado del callback o true
. El primer argumento que acepta el método attempt
es una "clave" de limitador de velocidad, que puede ser cualquier cadena que elijas y que represente la acción que se está limitando:
use Illuminate\Support\Facades\RateLimiter; $executed = RateLimiter::attempt( 'send-message:'.$user->id, $perMinute = 5, function() { // Send message... }); if (! $executed) { return 'Too many messages sent!';}
Si es necesario, puedes proporcionar un cuarto argumento al método attempt
, que es la "tasa de decaimiento", o el número de segundos hasta que se restablezcan los intentos disponibles. Por ejemplo, podemos modificar el ejemplo anterior para permitir cinco intentos cada dos minutos:
$executed = RateLimiter::attempt( 'send-message:'.$user->id, $perTwoMinutes = 5, function() { // Send message... }, $decayRate = 120,);
Incrementando Intentos Manualmente
Si deseas interactuar manualmente con el limitador de tasa, hay una variedad de otros métodos disponibles. Por ejemplo, puedes invocar el método tooManyAttempts
para determinar si una clave de limitador de tasa dada ha superado su número máximo de intentos permitidos por minuto:
use Illuminate\Support\Facades\RateLimiter; if (RateLimiter::tooManyAttempts('send-message:'.$user->id, $perMinute = 5)) { return 'Too many attempts!';} RateLimiter::increment('send-message:'.$user->id); // Send message...
Alternativamente, puedes usar el método remaining
para recuperar el número de intentos restantes para una clave dada. Si una clave dada tiene reintentos restantes, puedes invocar el método increment
para incrementar el número total de intentos:
use Illuminate\Support\Facades\RateLimiter; if (RateLimiter::remaining('send-message:'.$user->id, $perMinute = 5)) { RateLimiter::increment('send-message:'.$user->id); // Send message...}
Si deseas aumentar el valor para una clave de limitador de tasa dada en más de uno, puedes proporcionar la cantidad deseada al método increment
:
RateLimiter::increment('send-message:'.$user->id, amount: 5);
Determinando la Disponibilidad de Limitadores
Cuando una clave ya no tiene más intentos disponibles, el método availableIn
devuelve el número de segundos que quedan hasta que se puedan realizar más intentos:
use Illuminate\Support\Facades\RateLimiter; if (RateLimiter::tooManyAttempts('send-message:'.$user->id, $perMinute = 5)) { $seconds = RateLimiter::availableIn('send-message:'.$user->id); return 'You may try again in '.$seconds.' seconds.';} RateLimiter::increment('send-message:'.$user->id); // Send message...
Intentos de Borrado
Puedes restablecer el número de intentos para una clave de limitador de tasa dada utilizando el método clear
. Por ejemplo, puedes restablecer el número de intentos cuando un mensaje dado es leído por el receptor:
use App\Models\Message;use Illuminate\Support\Facades\RateLimiter; /** * Mark the message as read. */public function read(Message $message): Message{ $message->markAsRead(); RateLimiter::clear('send-message:'.$message->user_id); return $message;}