Skip to content

RateLimit API Reference

namespace Petrovo\RateLimit;

class RateLimiter

Veřejné Metody

setPath(string $storagePath): void

NUTNÉ: Nastaví cestu pro rate limit data. Musí být voláno během bootstrap!

Parametry: - $storagePath (string) – Absolutní cesta k adresáři (bez trailing slash)

Příklad:

// app/bootstrap.php (VYŽADOVÁNO)
RateLimiter::setPath(DIR . '/var/rate-limits');
// Nebo vlastní cesta:
RateLimiter::setPath('/tmp/rate-limits');

Chování: - Pokud setPath() není zavolán → RuntimeException při prvním check() - Cesta nemusí existovat (vytvoří se automaticky) - Trailing slash se automaticky odstraňuje - Adresář je vytvořen s permisemi 0755 (recursive)

Proč je to povinné? - Explicitní inicializace (fail-fast vs. silent fallback) - Jasné bootstrap požadavky - Léčí proti neočekávaným chybám


check(string $ip, int $maxRequests = 20, int $perSeconds = 60): bool

Zkontroluje, zda je request z dané IP adresy v limitech.

Parametry:

  • $ip (string) – IP adresa requestu
  • $maxRequests (int) – Maximální počet requestů (výchozí: 20)
  • $perSeconds (int) – Časové okno v sekundách (výchozí: 60)

Návratová hodnota:

  • true – Request je v limitech, povoluj ho
  • false – Limit je překročen, zamítni request (HTTP 429)

Příklad – Login Endpoint:

$ip = $_SERVER['REMOTE_ADDR'];

if (!RateLimiter::check($ip, 10, 300)) {  // 10 pokusů za 5 minut
    http_response_code(429);
    exit('Příliš mnoho pokusů. Zkus za 5 minut.');
}

// OK – zpracuj login

Příklad – Přísný API Limit:

if (!RateLimiter::check($ip, 5, 60)) {  // 5 requestů za minutu
    header('HTTP/1.1 429 Too Many Requests');
    exit(json_encode(['error' => 'Rate limit exceeded']));
}

Vnitřní Chování:

  • IP je hashována SHA-256 (prvních 16 znaků) → název souboru
  • Soubor je zamčen (flock) – zamezí race conditions
  • Staré timestampy mimo okno jsou odfiltrován (sliding window)
  • Pokud limit umožňuje → timestamp se uloží, vrátí true
  • Pokud limit zabraňuje → nic se neuloží, vrátí false
  • Fail-open: Pokud se nepodaří otevřít/zamknout soubor → vrátí true (bezpečnost)

getCount(string $ip, int $perSeconds = 60): int

Vrátí počet requestů ze dané IP v aktuálním okně (bez zamykání).

Parametry:

  • $ip (string) – IP adresa
  • $perSeconds (int) – Časové okno (výchozí: 60 sekund)

Návratová hodnota:

  • int – Počet requestů v okně (0 pokud IP nemá data)

Příklad – Monitorování:

$ip = $_SERVER['REMOTE_ADDR'];
$count = RateLimiter::getCount($ip, 60);

if ($count > 15) {
    // Podezřelá aktivita, log to
    error_log("Vysoká aktivita z $ip: $count requestů/min");
}

Poznámka:

  • Pouze čtení – bez zápisu do souboru
  • Bez file locking (rychlejší pro monitoring)
  • Vrátí 0 pokud soubor neexistuje

reset(string $ip): bool

Smazání všech rate limit dat pro danou IP (výmaz souboru).

Parametry:

  • $ip (string) – IP adresa pro resetování

Návratová hodnota:

  • true – Reset успешен (nebo soubor neexistoval)
  • false – Chyba při mazání souboru

Příklad – Admin Funkce:

// User přikazuje resetovat limit pro konkrétní IP
if ($_GET['action'] === 'reset-limit' && is_admin()) {
    $ip = $_GET['ip'];
    if (RateLimiter::reset($ip)) {
        echo "Reset limit pro $ip OK";
    } else {
        echo "Chyba při resetu";
    }
}

Příklad – Reset po Úspěšném Login:

// Uživatel se úspěšně přihlásil – smaž limit
if ($login_success) {
    RateLimiter::reset($_SERVER['REMOTE_ADDR']);
    // Teď má čistý štít pro další pokusy
}


Interní Metody

Následující metody jsou private a nejsou určeny k přímému volání:

resolveFilePath(string $ip): string

Vrátí cestu souboru pro danou IP. Používá SHA-256 hash prvních 16 znaků.

getCacheDir(): string

Vrátí cestu k adresáři rate-limits (bez vytvoření).

ensureCacheDir(): void

Zajistí, že adresář existuje (vytvoří pokud potřeba).

cleanupOldFiles(): void

Smaž soubory starší 1 hodinu. Volá se automaticky (~1% requestů).


Chybové Chování

Fail-Open Design

Pokud cokoliv selže (chyba souborů, zamykání, JSON), RateLimiter vrátí true (povolí request):

$fp = fopen($file, 'c+');
if ($fp === false) {
    return true;  // Chyba souborů → povoleno (bezpečnost)
}

if (!flock($fp, LOCK_EX)) {
    fclose($fp);
    return true;  // Nemůž zamknout → povoleno
}

Důvod: Raději nechť přejde pár extra requestů, než aby brániš legitimnímu provozu.


Příklady Standardních Limitů

// Login endpoint – střídmě
RateLimiter::check($ip, 10, 300);  // 10 pokusů / 5 minut

// API endpoint – normálně
RateLimiter::check($ip, 100, 60);  // 100 req / minutu

// Veřejný formulář (kontakt) – velmi přísně
RateLimiter::check($ip, 3, 3600);  // 3 / hodina

// Password reset – přísně
RateLimiter::check($ip, 5, 3600);  // 5 / hodina

// API webhook – volné
RateLimiter::check($ip, 1000, 60); // 1000 / minutu

Backcompat s Příponou .json

RateLimiter pracuje s JSON soubory v var/rate-limits/:

{
  "requests": [timestamp1, timestamp2, ...]
}

Pole je pole Unix timestampů. Žádné další metadata se neukládá (je to maximálně jednoduché).


Další Čtení