Rate-limiting

Introduzione

Laravel include un’astrazione semplice da usare per il rate limiting che, insieme alla cache dell’applicazione, fornisce un modo facile per limitare qualsiasi azione durante una finestra di tempo specificata.

Se sei interessato al rate limiting delle richieste HTTP in entrata, consulta la documentazione del middleware rate limiter.

Configurazione della Cache

Tipicamente, il rate limiter utilizza la cache predefinita dell’applicazione come definito dalla chiave default nel file di configurazione cache della tua applicazione. Tuttavia, puoi specificare quale driver di cache deve usare il rate limiter definendo una chiave limiter nel file di configurazione cache della tua applicazione:

'default' => env('CACHE_STORE', 'database'),

'limiter' => 'redis',

Uso Base

La facade Illuminate\Support\Facades\RateLimiter può essere utilizzata per interagire con il rate limiter. Il metodo più semplice offerto dal rate limiter è il metodo attempt, che limita il tasso di esecuzione di una determinata callback per un dato numero di secondi.

Il metodo attempt restituisce false quando la callback non ha tentativi rimanenti disponibili; altrimenti, il metodo attempt restituirà il risultato della callback o true. Il primo argomento accettato dal metodo attempt è una "key" del rate limiter, che può essere qualsiasi stringa a tua scelta che rappresenta l’azione che viene limitata:

    use Illuminate\Support\Facades\RateLimiter;

    $executed = RateLimiter::attempt(
        'send-message:'.$user->id,
        $perMinute = 5,
        function() {
            // Send message...
        }
    );

    if (! $executed) {
      return 'Too many messages sent!';
    }

Se necessario, puoi fornire un quarto argomento al metodo attempt, che è il "decay rate", ovvero il numero di secondi prima che i tentativi disponibili vengano resettati. Ad esempio, possiamo modificare l’esempio sopra per permettere cinque tentativi ogni due minuti:

    $executed = RateLimiter::attempt(
        'send-message:'.$user->id,
        $perTwoMinutes = 5,
        function() {
            // Send message...
        },
        $decayRate = 120,
    );

Incremento Manuale dei Tentativi

Se desideri interagire manualmente con il rate limiter, sono disponibili diverse altre metodologie. Ad esempio, puoi invocare il metodo tooManyAttempts per determinare se una determinata chiave del rate limiter ha superato il numero massimo di tentativi consentiti per minuto:

use Illuminate\Support\Facades\RateLimiter;

if (RateLimiter::tooManyAttempts('send-message:'.$user->id, $perMinute = 5)) {
    return 'Troppi tentativi!';
}

RateLimiter::increment('send-message:'.$user->id);

// Invia messaggio...

In alternativa, puoi utilizzare il metodo remaining per recuperare il numero di tentativi rimanenti per una determinata chiave. Se una chiave ha tentativi rimanenti, puoi invocare il metodo increment per aumentare il numero totale di tentativi:

use Illuminate\Support\Facades\RateLimiter;

if (RateLimiter::remaining('send-message:'.$user->id, $perMinute = 5)) {
    RateLimiter::increment('send-message:'.$user->id);

    // Invia messaggio...
}

Se desideri incrementare il valore per una determinata chiave del rate limiter di più di uno, puoi fornire l’ammontare desiderato al metodo increment:

RateLimiter::increment('send-message:'.$user->id, amount: 5);

Determinare la Disponibilità del Limiter

Quando una chiave non ha più tentativi disponibili, il metodo availableIn restituisce il numero di secondi rimanenti prima che siano disponibili altri tentativi:

use Illuminate\Support\Facades\RateLimiter;

if (RateLimiter::tooManyAttempts('send-message:'.$user->id, $perMinute = 5)) {
    $seconds = RateLimiter::availableIn('send-message:'.$user->id);

    return 'Puoi riprovare tra '.$seconds.' secondi.';
}

RateLimiter::increment('send-message:'.$user->id);

// Invia messaggio...

Resettare i Tentativi

Puoi resettare il numero di tentativi per una specifica chiave del rate limiter usando il metodo clear. Ad esempio, puoi resettare i tentativi quando un messaggio viene letto dal destinatario:

use App\Models\Message;
use Illuminate\Support\Facades\RateLimiter;

/**
 * Segna il messaggio come letto.
 */
public function read(Message $message): Message
{
    $message->markAsRead();

    RateLimiter::clear('send-message:'.$message->user_id);

    return $message;
}
Lascia un commento

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *