[−][src]Crate limitation
A rate limiter using a fixed window counter for arbitrary keys, backed by Redis.
About
This library provides a fixed window counter for arbitrary keys backed by a Redis instance. The period length and per-period maximum limit are configurable on setup. The communication with the backend is performing in a non-blocking, asynchronous fashion allowing the library to pair with other async frameworks such as Tokio, Actix, etc.
Note: Currently pre-async/await Futures are used (that is Futures 0.1.x) but that may be upgraded in the near future as the Rust 1.39.0 release is near.
Usage
Add limitation
to your Cargo.toml
:
[dependencies]
limitation = "0.1.1"
Quick Example
The primary type is the Limiter
which uses a builder to construct itself. Once built, use
the count
method with a key representing a user, a session, an interaction, etc. Note that
count
is a Future and therefore has to be driving to completion with a runtime. For example,
to run one count on a key of "10.0.0.5"
:
use limitation::Limiter; use futures::Future; // Build a Limiter with a default rate with a local running Redis instance let limiter = Limiter::build("redis://127.0.0.1/").finish()?; // The key to count and track let key = "10.0.0.5"; // Start and run a Tokio runtime to drive the Future to completion tokio::run( limiter // Count returns a Status if the key is under the limit and an `Error::LimitExceeded` // containing a Status if the limit has been exceeded .count(key) // This example deals with both limit exceeded and any Redis connection issues. In this // case we'll print the error to the standard error stream to show the current limit // status .map_err(|err| eprintln!("err: {}", err)) // In this case we are under the limit and can print out the limit status to the // standard output stream .and_then(|status| { println!("ok: {:?}", status); Ok(()) }), );
The Limiter Builder
The builder for the Limiter
has 2 settings which can be customized to the use case:
limit
: The high water mark for number of requests in the period. The default is5000
.period
: ADuration
for the period window. The default is 60 minutes.
use limitation::Limiter; use std::time::Duration; let limiter = Limiter::build("redis://127.0.0.1/") .limit(5) .period(Duration::from_secs(10)) .finish()?;
Examples
A simple example that uses this library can be found in limitation-example.
Related Projects and References
The primary inspiration for the implementation was a blog post called An alternative approach to building a simple API Rate limiter using NodeJS and Redis by Atul R.
Other research and references used for this library:
- https://nordicapis.com/everything-you-need-to-know-about-api-rate-limiting/
- https://hechao.li/2018/06/25/Rate-Limiter-Part1/
- https://www.figma.com/blog/an-alternative-approach-to-rate-limiting/
- https://engagor.github.io/blog/2017/05/02/sliding-window-rate-limiter-redis/
Ideas and Future Work
These are some ideas and potential future work for this project. If you're reading this then maybe you're curious or interesting in helping out? Great! Be sure to check out the Contributing section and dig in!
- Investigate and offer alternative rate-limiting algorithms, notably a Sliding Window solution.
- Add async Redis connection pooling with the
bb8
andbb8-redis
crates to reduce connection establishment delays. - Add a
status
method onLimiter
which returns they key'sStatus
without counting a request. - Add
RedisServer
support in an integration testing suite, similar to the infrastructure in the redis crate.
Structs
Builder | A builder for a |
Limiter | A rate limiter using a fixed window counter, backed by Redis. |
Status | A report for a given key containing the limit status. |
Enums
Error | Error type for this crate. |