ApiClientRateLimiter
in package
Request limits per application key.
Two levels:
- the whole application: a 1 s window (spikes) and a 1 min window (sustained load), hitClient();
- one caller under the key: a signed-in user by
userIdfrom 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
KEY_PREFIX
private
string
KEY_PREFIX
= 'ratelimit:apiclient:'
Properties
$config read-only
private
ApiClientKeyConfig
$config
$rateLimit read-only
private
RateLimit
$rateLimit
$redis read-only
private
Client|null
$redis
= null
$useRedis read-only
private
bool
$useRedis
= true
Methods
__construct()
public
__construct(ApiClientKeyConfig $config, RateLimit $rateLimit[, Client|null $redis = null ][, bool $useRedis = true ]) : mixed
Parameters
- $config : ApiClientKeyConfig
- $rateLimit : RateLimit
- $redis : Client|null = null
- $useRedis : bool = true
hitCaller()
Applies the limit of one caller under the key: a signed-in user by account, an anonymous one by address.
public
hitCaller(ApiClientIdentity $client, int|null $userId, string $ip[, int|null $now = null ]) : ApiClientLimitResult
Parameters
- $client : ApiClientIdentity
- $userId : int|null
-
from the JWT payload (never from the request);
nullor0means not signed in - $ip : string
- $now : int|null = null
Return values
ApiClientLimitResulthitClient()
Applies the whole-application limit: the one-second window first, then the one-minute window.
public
hitClient(ApiClientIdentity $client[, int|null $now = null ]) : ApiClientLimitResult
Parameters
- $client : ApiClientIdentity
- $now : int|null = null
Return values
ApiClientLimitResultcountInRedis()
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]