CoolCMS API

ApiClientRateLimiter
in package

FinalYes

Request limits per application key.

Two levels:

  1. the whole application: a 1 s window (spikes) and a 1 min window (sustained load), hitClient();
  2. one caller under the key: a signed-in user by userId from the JWT, otherwise by address, 1 min window, hitCaller().

Fixed windows, not a sliding log like RedisRateLimit: the one-second window is counted on every external request. A sliding log (sorted set) keeps one entry per request and costs four commands per window; a fixed window is one INCR plus EXPIRE on the key ratelimit:apiclient:<id>:<window>:<window number>, with all windows of the client in one pipeline (one round trip to Redis). The price is that at a window boundary up to twice the limit passes, which is enough to protect the server from an application that hogs it.

Without Redis (ratelimit.useRedis: false) every window goes through the configured RateLimit, i.e. DbRateLimit (a fixed window in cms_system_rate_limit, INSERT … ON DUPLICATE KEY UPDATE plus SELECT). It works the same but costs two queries per window: a request with a key adds six queries for three windows.

Fail-open like the rest of the limits: a storage outage does not stop the request (it is logged to the auth log).

Table of Contents

Constants

KEY_PREFIX  : string = 'ratelimit:apiclient:'

Properties

$config  : ApiClientKeyConfig
$rateLimit  : RateLimit
$redis  : Client|null
$useRedis  : bool

Methods

__construct()  : mixed
hitCaller()  : ApiClientLimitResult
Applies the limit of one caller under the key: a signed-in user by account, an anonymous one by address.
hitClient()  : ApiClientLimitResult
Applies the whole-application limit: the one-second window first, then the one-minute window.
countInRedis()  : array<int, int>|null
Counts all windows in one pipeline. A Redis outage yields zero counts (fail-open); `null` only when the pipeline cannot be created, in which case the configured {@see RateLimit} takes the windows over.
hitWindows()  : ApiClientLimitResult

Constants

Properties

Methods

countInRedis()

Counts all windows in one pipeline. A Redis outage yields zero counts (fail-open); `null` only when the pipeline cannot be created, in which case the configured {@see RateLimit} takes the windows over.

private countInRedis(int $now, array<int, array{0: string, 1: string, 2: int, 3: int}> $windows) : array<int, int>|null
Parameters
$now : int
$windows : array<int, array{0: string, 1: string, 2: int, 3: int}>
Return values
array<int, int>|null —

number of requests in the current window, in the same order as $windows

hitWindows()

private hitWindows(int $now, array<int, array{0: string, 1: string, 2: int, 3: int}> $windows) : ApiClientLimitResult
Parameters
$now : int
$windows : array<int, array{0: string, 1: string, 2: int, 3: int}>

[name, key, limit, window length in seconds]

Return values
ApiClientLimitResult
On this page

Search results