README updates
This commit is contained in:
parent
740f8bb1ce
commit
79f799bd7b
87
README.md
87
README.md
@ -3,3 +3,90 @@
|
|||||||
Very simple reusable redis-backed rate limiting code. Designed for OpenStates.org.
|
Very simple reusable redis-backed rate limiting code. Designed for OpenStates.org.
|
||||||
|
|
||||||
![Test](https://github.com/jamesturk/rrl/workflows/Test/badge.svg)
|
![Test](https://github.com/jamesturk/rrl/workflows/Test/badge.svg)
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
`rrl`, as the name implies, requires a [Redis](https://redis.io) server.
|
||||||
|
|
||||||
|
`rrl` is entirely configured by environment variables:
|
||||||
|
|
||||||
|
**RRL_REDIS_HOST** - hostname of Redis instance (default: *localhost*)
|
||||||
|
**RRL_REDIS_PORT** - port of Redis instance (default: *6379*)
|
||||||
|
**RRL_REDIS_DB** - database ID to use for RRL (default: *0*)
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Usage can be throttled on a per-minute, per-hour, and/or per-day basis.
|
||||||
|
|
||||||
|
`rrl` has the concept of a `Tier` which associates a name with a set of limitations, for instance:
|
||||||
|
|
||||||
|
```
|
||||||
|
# create two tiers
|
||||||
|
bronze = Tier(name="bronze", per_minute=1, per_hour=0, per_day=500)
|
||||||
|
silver = Tier(name="silver", per_minute=5, per_hour=0, per_day=4000)
|
||||||
|
```
|
||||||
|
|
||||||
|
These tiers do not use the per_hour feature, but will limit users to 1 or 5 requests per minute respectively. There's also a daily limit at 500 or 4000 requests per day.
|
||||||
|
|
||||||
|
Then you'll need an instance of `rrl.RateLimiter`, which will be instantiated with these tiers:
|
||||||
|
|
||||||
|
```
|
||||||
|
limiter = RateLimiter(tiers=[bronze, silver])
|
||||||
|
```
|
||||||
|
|
||||||
|
Then to apply limiting, you'll call the `check_limit` function, which takes three parameters:
|
||||||
|
|
||||||
|
* `zone` - Limits are considered unique per zone. So if you want calls against your geocoding API to count against a different limit than your user API you could pass those as unique zones.
|
||||||
|
* `key` - A unique-per user key, often the user's API key or username. (Note: `rrl` does not know if a key is valid or not, that validation should be in your application and usually occur before the call to `check_limit`.)
|
||||||
|
* `tier_name` - The name of one of the tiers as specified when instantiating the `RateLimiter` class. (Note: `rrl` does not have a concept of which users are in which tier, that logic should be handled by your key validation code.)
|
||||||
|
|
||||||
|
Example call:
|
||||||
|
|
||||||
|
```
|
||||||
|
limiter.check_limit(zone="api", key="1234", tier_name="bronze")
|
||||||
|
```
|
||||||
|
|
||||||
|
This call will return without any error if the call is deemed allowed.
|
||||||
|
|
||||||
|
If any of the rate limits are exceeded it will instead raise a `RateLimitExceeded` exception describing which limit was exceeded.
|
||||||
|
If multiple limits were exceeded it will return the shortest limit violated.
|
||||||
|
|
||||||
|
## Advanced Usage
|
||||||
|
|
||||||
|
### Obtaining Usage Information
|
||||||
|
|
||||||
|
Your `RateLimiter` instance also has a method named `get_usage_since`, which takes four parameters:
|
||||||
|
|
||||||
|
* `zone` - Which usage zone you're requesting usage information for.
|
||||||
|
* `key` - Which key you're requesting usage information for.
|
||||||
|
* `start` - Date that you'd like usage since, as a `datetime.date` object.
|
||||||
|
* `end` - Optional end date if you'd only like usage within a certain window, otherwise the current day is used.
|
||||||
|
|
||||||
|
This will return a list of `DailyUsage` dataclasses with the following attributes:
|
||||||
|
|
||||||
|
* `date` - `datetime.date`
|
||||||
|
* `calls` - Number of calls made on that date.
|
||||||
|
|
||||||
|
This method can be useful for showing users an overview of their data.
|
||||||
|
|
||||||
|
### Advanced Configuration
|
||||||
|
|
||||||
|
When instantiating a `RateLimiter` there are several keyword-only parameters you may set:
|
||||||
|
|
||||||
|
**prefix**
|
||||||
|
|
||||||
|
Passing a prefix like:
|
||||||
|
```
|
||||||
|
limiter = RateLimiter(tiers, prefix="v1")
|
||||||
|
```
|
||||||
|
will scope all calls to limiter to a given prefix, this can be useful if you want multiple limiters but want to ensure that they do not interfere with one another.
|
||||||
|
|
||||||
|
**use_redis_time**
|
||||||
|
|
||||||
|
`True` by default, but if you set to `False` the application's system time will be used instead.
|
||||||
|
|
||||||
|
The tradeoff here is one fewer call to Redis per call to `check_limit`, but if your machines experience any clock drift unexpected results may occur.
|
||||||
|
|
||||||
|
**track_daily_usage**
|
||||||
|
|
||||||
|
`True` by default, but if set to `False`, `rrl` will not store the necessary information to make `get_usage_since` work. This results in a slight overhead reduction, but the usage information will not be stored in Redis and will be impossible to retrieve.
|
||||||
|
Loading…
Reference in New Issue
Block a user