You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The lookup keys for more granular control are specified below.
@@ -53,46 +53,61 @@ The "Postman Samples" folder contains a sample [Postman](https://www.getpostman.
53
53
## Overview
54
54
The plugin registers a [global request filter](https://github.com/ServiceStack/ServiceStack/wiki/Request-and-response-filters#global-request-filters). Every time a request is received a check is made using a [Redis LUA script](http://redis.io/commands/eval). If the specified limits have not been hit then the request is processed as expected. However, if the limit has been reached then a [429](https://tools.ietf.org/html/rfc6585#page-3) "Too Many Requests" response is generated and processing of the request is halted.
55
55
56
-
Two possible headers are returned from any endpoint that is protecte: x-ratelimit-request and x-ratelimit-user. They will show the seconds duration, the limit and how many remaining calls are available per request, or user respectively.
56
+
Two possible headers are returned from any endpoint that is protected: `x-ratelimit-request` and `x-ratelimit-user`. They will show the seconds duration, the limit and how many remaining calls are available per request, or user respectively.
57
57
58
58
### Rate Limits
59
59
60
60
At a high level, rate limits can be set at either **User** or **Resource** level (by default a resource in this instance is the DTO type name). Limits are fetched from [IAppSettings](https://github.com/ServiceStack/ServiceStack/wiki/AppSettings) and can be set at the following levels, in order of precedence:
61
61
62
-
* User for resource - User 123 can make X requests to a specific resource (e.g. /api/products). (config key: "lmt:{resourceName}:{userId}")
63
-
* User - User 123 can make X total requests for specific time period(s). (config key: "lmt:usr:{userId}")
64
-
* User fallback - Fallback total request limit for users without specific defaults. (config key: "lmt:usr:default")
65
-
* Resource - Each user can make X requests to a resource (e.g. /api/products) for specific time period(s). (config key: "lmt:{resourceName}".)
66
-
* Resource fallback - Fallback limit for requests individual users can make to a resource. (config key: "lmt:default")
62
+
| Order | Type | Description | Default Key |
63
+
| --- | --- | --- | --- |
64
+
| 1 | User for resource | User 123 can make X requests to a specific resource (e.g. /api/products) |`ss/lmt/{resourceName}/{userId}`|
65
+
| 2 | User | User 123 can make X total requests for specific time period(s) |`ss/lmt/usr/{userId}`|
66
+
| 3 | User fallback | Fallback total request limit for users without specific defaults |`ss/lmt/usr/default`|
67
+
| 4 | Resource | Each user can make X requests to a resource (e.g. /api/products) for specific time period(s) |`ss/lmt/{resourceName}`|
68
+
| 5 | Resource fallback | Fallback limit for requests individual users can make to a resource. |`ss/lmt/default`|
67
69
68
70
User limits AND resource limits will be calculated at the same time (if present). User limits are calculated first. If a limit is hit subsequent wider limits are not incremented (e.g. if limit per second is hit, limit per minute would not be counted).
69
71
72
+
#### Customising Keys
73
+
74
+
It is possible to change both the prefix, default *ss* (to distinguish ServiceStack settings), and delimiter, default */*, as static variables of the `LimitKeyGenerator` class. For example:
75
+
76
+
```csharp
77
+
LimitKeyGenerator.Delimiter="-";
78
+
LimitKeyGenerator.Prefix=null;
79
+
```
80
+
81
+
Would produce keys like `lmt-default` rather than `ss/lmt/default`.
82
+
70
83
#### Limit Representation
71
84
All limits are per second and are stored as a LimitGroup object serialised to JSV. For example, the following shows a limit of 5 requests per second, 15 per minute (60s) and 100 per hour (3600s):
A LUA script is used for doing the heavy lifting and keeping track of limit totals. To save bandwith on calls to Redis the [EVALSHA](http://redis.io/commands/evalsha) command is used to call a LUA script which has previously been [loaded](http://redis.io/commands/script-load).
78
91
79
-
The default implementation of ILimitProvider (see below) will check IAppSettings for a value with key "script:ratelimit". This value will be the SHA1 of the script to use. Using this method means that the script can be managed external to the plugin.
92
+
The default implementation of ILimitProvider (see below) will check IAppSettings for a value with key *ss/script/ratelimit*. This value will be the SHA1 of the script to use. Using this method means that the script can be managed external to the plugin.
80
93
81
94
If an AppSetting is not found with the specified key then the RateLimitHash.lua script is loaded, the SHA1 is stored and used for subsequent requests.
82
95
83
96
**Note:** The RateLimitHash.lua script does not currently use a sliding expiry, instead is resets every X seconds. E.g. if the limit is for 50 requests in 3600 seconds (1 hour) then 50 requests could be made at 10:59 and then 50 request can be made at 11:01. This is something that may be looked at in the future.
84
97
85
98
### Extensibility
86
-
There are a few extension point that can be set when adding the plugin:
87
-
88
-
* CorrelationIdExtractor - This is a delegate function that customises how an individual request is identified. By default it uses the value of HTTP Header with name specified by CorrelationIdHeader property. **Note:** This is primarily required for when a ServiceStack service calls subsequent ServiceStack services that all use this plugin as it will avoid user totals being incremented multiple times for the same request.
89
-
* CorrelationIdHeader - The name of the header used for extracting correlation Id from request (if using default method). Default: x-mac-requestid.
90
-
* StatusDescription - the status description returned when limit is breached. Default "Too many requests".
91
-
* LimitStatusCode - the status code returned when limit is breached. Default 429.
92
-
* KeyGenerator - an implementation of IKeyGenerator for generating config lookup key(s) for request. Defaults outlined above.
93
-
* LimitProvider - an implementation of ILimitProvider for getting RateLimits for current request. Default uses IKeyGenerator keys to lookup IAppSettings.
94
-
95
-
These are all properties of the RateLimitFeature class and can be set when instantiating the plugin
99
+
There are a few extension point that can be set when adding the plugin. These are all properties of the RateLimitFeature class and can be set when instantiating the plugin:
100
+
101
+
| Property | Description | Notes |
102
+
| --- | --- | --- |
103
+
| CorrelationIdExtractor | This is a delegate function that customises how an individual request is identified. | By default it uses the value of HTTP Header with name specified by CorrelationIdHeader property. This is primarily required for when a ServiceStack service calls subsequent ServiceStack services that all use this plugin as it will avoid user totals being incremented multiple times for the same request. |
104
+
| CorrelationIdHeader | The name of the header used for extracting correlation Id from request (if using default method) | Default: `x-mac-requestid`|
105
+
| StatusDescription | The status description returned when limit is breached | Default: "Too many requests" |
106
+
| LimitStatusCode | the status code returned when limit is breached. | Default: 429 |
107
+
| KeyGenerator | an implementation of IKeyGenerator for generating config lookup key(s) for request. | Defaults outlined above |
108
+
| LimitProvider | an implementation of ILimitProvider for getting RateLimits for current request. | Default uses `IKeyGenerator` keys to lookup `IAppSettings`|
0 commit comments