Support: [email protected]
Basic rate-limiting middleware for Horse. Use to limit repeated requests to public APIs and/or endpoints such as password reset.
For install in your project using boss:
$ boss install github.com/dliocode/horse-ratelimit
- Dependence - Store - ClientIP - RedisClient
- Memory Store (default, built-in) - stores current in-memory in the Horse process. Does not share state with other servers or processes.
- RedisStore: Samples - Model 4
For an API-only server where the ratelimit should be applied to all requests: Ex: Store Memory
uses Horse, Horse.RateLimit;
begin
THorse
.Use(THorseRateLimit.New())
.Get('/ping',
procedure(Req: THorseRequest; Res: THorseResponse; Next: TProc)
begin
Res.Send('pong');
end);
THorse.Listen(9000);
end.
Create multiple instances to different routes: Identification should always be used when using multiple instances.
uses Horse, Horse.RateLimit;
begin
THorse
.Get('/ping', THorseRateLimit.New('ping'),
procedure(Req: THorseRequest; Res: THorseResponse; Next: TProc)
begin
Res.Send('pong');
end)
.Get('/book', THorseRateLimit.New('book'),
procedure(Req: THorseRequest; Res: THorseResponse; Next: TProc)
begin
Res.Send('The book!');
end)
.Get('/login', THorseRateLimit.New('login',10,60),
procedure(Req: THorseRequest; Res: THorseResponse; Next: TProc)
begin
Res.Send('My Login with Request Max of 10 every 60 seconds!');
end);
THorse.Listen(9000);
end.
Settings use:
uses Horse, Horse.RateLimit;
var
Config: TRateLimitConfig;
begin
Config.Id := 'ping'; // Identification
Config.Limit := 5; // Limit Request
Config.Timeout := 30; // Timeout in seconds
Config.Message := ''; // Message return
Config.Headers := True; // Show in Header X-RateLimit-*
Config.Store := nil; // Default TMemoryStore
Config.SkipFailedRequest := False; // Undo if the response request was failed
Config.SkipSuccessRequest := False; // Undo if the response request was successful
THorse
.Get('/ping', THorseRateLimit.New(Config),
procedure(Req: THorseRequest; Res: THorseResponse; Next: TProc)
begin
Res.Send('pong');
end);
// Max of 30 Request in 5 minutes with return custom message
Config.Id := 'Test';
Config.Limit := 30;
Config.Timeout := 5 * 60;
Config.Message := 'My Custom Message';
Config.Headers := True;
THorse.Get('/test', THorseRateLimit.New(Config),
procedure(Req: THorseRequest; Res: THorseResponse; Next: TProc)
begin
Res.Send('ok');
end);
THorse.Listen(9000);
end.
Note: Stores require additional configuration, such as custom prefixes, when using multiple instances.
Identification should always be used when using multiple instances..
Max number of request during Timeout
in seconds before sending a 429 response.
It must be a number. The default is 60
.
Timeframe for which requests are checked/remembered. Also used in the Retry-After header when the limit is reached.
Note: with non-default stores, you may need to configure this value twice, once here and once on the store. In some cases the units also differ (e.g. seconds vs miliseconds)
Defaults to 60
(1 minute).
Error message sent to user when Limit
is exceeded.
It must be a string. The default is 'Too many requests, please try again later.'
.
Enable headers for request limit (X-RateLimit-Limit
) and current usage (X-RateLimit-Remaining
) on all responses and time to wait before retrying (Retry-After
) when Limit
is exceeded.
Defaults to false
. Behavior may change in the next major release.
When set to true
, failed requests won't be counted. Request considered failed when:
- response status >= 400
(Technically they are counted and then un-counted, so a large number of slow requests all at once could still trigger a rate-limit. This may be fixed in a future release.)
Defaults to false
.
When set to true
successful requests (response status < 400) won't be counted.
(Technically they are counted and then un-counted, so a large number of slow requests all at once could still trigger a rate-limit. This may be fixed in a future release.)
Defaults to false
.
The storage to use when persisting rate limit attempts.
By default, the MemoryStore is used.
Available data stores are:
- MemoryStore: (default) Simple in-memory option. Does not share state when app has multiple processes or servers.
- RedisStore: Samples - Model 4
You may also create your own store. It must implement the IStore to function
Usage:
To use it you must add to uses Store.Redis
with the function TRedisStore.New()
.
Ex: Store Redis
uses Horse, Horse.RateLimit, Store.Redis;
begin
THorse
.Use(THorseRateLimit.New('ping', 10, 60, '', TRedisStore.New())) // Add TRedisStore.New()
.Get('/ping',
procedure(Req: THorseRequest; Res: THorseResponse; Next: TProc)
begin
Res.Send('pong');
end);
THorse.Listen(9000);
end.
How to configure host, port in Redis
TRedisStore.New('HOST','PORT','NAME CLIENTE')
1st Parameter - HOST - Default: 127.0.0.1
2st Parameter - PORT - Default: 6379
3st Parameter - ClientName - Default: Empty
MIT © Danilo Lucas