Class List
- App\Middleware\Cors
- App\Middleware\Auth
- App\Middleware\Env
- AppMin
- Application
- Route
- Data\Database
- Data\Db2Database
- Data\OdbcDatabase
- Data\Validator
- Data\KeyValue\SqliteStorage
- Data\Log\FileLogger
- Data\Log\HtmlLogger
- Encoding\Base64Url
- Encoding\Json
- Encoding\Utf8
- Environment\DotEnv
- Environment\System
- FileSystem\Search
- FileSystem\Security
- FileSystem\Sync
- Lang\I18N
- Lang\L10N
- Lang\Time
- Media\Image
- Net\Config
- Net\Email
- Net\HttpClient
- Net\HttpResponse
- Net\IP
- Net\SmtpClient
- Security\Crypto
- Security\Password
- Security\Crypto\Encryption
- Security\Crypto\FileEncryption
- Security\Crypto\JWT
- Security\Crypto\PublicKey
- Security\Crypto\Random
- Security\Crypto\SignedData
- Security\Web\CsrfSession
- Security\Web\CsrfStateless
- Security\Web\RateLimit
- Web\Request
- Web\Response
FastSitePHP\Security\Web\RateLimit
Rate limiting can be used to limit the number of requests or actions that a user makes in a given time frame.
Some examples:
- A Web API allowing users to submit no more than 1 request every second.
- No more than 2 new accounts per day per IP address.
- Limit users from sending more than 10 messages per hour.
FastSitePHP's Rate Limit class is designed to provide an easy-to-use interface for defining and enforcing rate limits.
Source Code
Related Links
- https://en.wikipedia.org/wiki/Rate_limiting
- https://medium.com/smyte/rate-limiter-df3408325846
- https://www.figma.com/blog/an-alternative-approach-to-rate-limiting/
- https://konghq.com/blog/how-to-design-a-scalable-rate-limiting-algorithm/
- https://blog.cloudflare.com/counting-things-a-lot-of-different-things/
- https://stripe.com/blog/rate-limiters
Example Code
Security - Rate Limiting
// Rate Limit Class
$rate_limit = new \FastSitePHP\Security\Web\RateLimit();
// Using the RateLimit class requires an instance of
// [\FastSitePHP\Data\KeyValue\StorageInterface].
// In this example SQLite is used. When multiple servers are used behind
// a load balancer an in-memory cache db such as Redis can be used.
$file_path = sys_get_temp_dir() . '/ratelimit-cache.sqlite';
$storage = new \FastSitePHP\Data\KeyValue\SqliteStorage($file_path);
// There are 2 required options [storage] and [id].
// [id] represents the user - IP Address, User ID, etc.
//
// [max_allowed] and [duration] will commonly be used and represent
// the rate at which the event is allowed. If not specified then a
// default of 1 is used which allows for 1 request per second.
$options = [
'max_allowed' => 1, // Requests, Events, etc
'duration' => 1, // In seconds
'storage' => $storage,
'id' => $_SERVER['REMOTE_ADDR'],
];
// Check the Request
list($allowed, $headers) = $rate_limit->allow($options);
// $allowed = bool
// $headers = Array of headers that can be used for logic
// or sent with the response
// One thing to be aware of when filtering by IP is that many users can have
// the same IP if they are accessing your site from the same office or location.
// Option examples:
// Limit to 10 requests every 20 seconds
$options = [ 'max_allowed' => 10, 'duration' => 20, ];
// Limit to 2 requests per minute
$options = [ 'max_allowed' => 2, 'duration' => 60, ];
// Limit to 2 requests per day
$options = [ 'max_allowed' => 10, 'duration' => (60 * 60 * 24), ];
// If using the [RateLimit] class for multiple
// uses then you need to specify an optional key.
$options = [ 'key' => 'messages-sent' ];
$options = [ 'key' => 'accounts-created' ];
// The [RateLimit] class allows for different rate limiting algorithms;
// the default is 'fixed-window-counter' which puts a fixed amount on
// the number of requests for the given duration, but allows for bursts.
// The 'token-bucket' allows for rate limiting at a timed rate however
// it can allow for a higher number requests than the specified [max_allowed].
//
// For basic usage with a small number of [max_allowed] such as
// "1 request per second" they will behave the same, however if specifying
// a larger number such as "10 requests per 20 seconds" then there will
// be a difference so if you are using rate limiting for web requests with
// a larger number you may want to compare the differences using example code
// and see related links in the API docs.
//
$options = [ 'algo' => 'fixed-window-counter' ];
$options = [ 'algo' => 'token-bucket' ];
// The [filterRequest()] function can be used to filter the request.
// When used if the user's rate limit is reached then a 429 [Too Many Requests]
// response is sent and [exit()] is called to stop the script execution.
$filter_request = function() use ($app, $storage) {
// Get User IP (example if using a load-balancer)
$req = new \FastSitePHP\Web\Request();
$user_ip = $req->clientIp('from proxy');
// Check rate
$rate_limit = new \FastSitePHP\Security\Web\RateLimit();
$rate_limit->filterRequest($app, [
'storage' => $storage,
'id' => $user_ip,
]);
};
$app->get('/api', function() {})->filter($filter_request);
// When using [filterRequest()] the following Response Headers can sent
// to the client depending on which options are used:
// Retry-After Standard Header
// X-RateLimit-Limit Human readable description of the rate limit
// X-RateLimit-Remaining Requests allowed for the given time frame
// X-RateLimit-Reset Unix Timestamp for the limit to reset
Methods
filterRequest(Application $app, array $options)
Filter the request if it is allowed based on a rate limit. If the user's rate limit is reached then a 429 [Too Many Requests] response is sent and [exit()] is called to stop the script execution.
The same options used for [allow()] are used here.
allow(array $options)
Check if a request or action is allowed based on a rate limit.
Required Options:
- [storage]: Object - Instance of [FastSitePHP\Data\KeyValue\StorageInterface]
- [id]: Id assigned to the user or request. For example the client's IP Address or a user id
Common Optional Options:
- [max_allowed] (int): Maximum number of requests allowed for the specified duration
- [duration] (int): Time in sections
Additional Options:
- [key]: String value to prefix when saving a key-value-pair.
This would be used if you are using the RateLimiter for multiple actions in the same site.
- [algo]: Algorithm to use ['fixed-window-counter' or 'token-bucket']. Defaults to 'fixed-window-counter'.
Returns: array - list($allowed, $headers)