Expand description
A middleware for actionable that provides rate-limiting backed by governor.
§Features:
- Simple to use
- High customizability
- High performance
- Robust yet flexible API
§How does it work?
Each governor middleware has a configuration that stores a quota. The quota specifies how many requests can be sent from an IP address before the middleware starts blocking further requests.
For example if the quota allowed ten requests a client could send a burst of ten requests in short time before the middleware starts blocking.
Once at least one element of the quota was used the elements of the quota will be replenished after a specified period.
For example if this period was 2 seconds and the quota was empty it would take 2 seconds to replenish one element of the quota. This means you could send one request every two seconds on average.
If there was a quota that allowed ten requests with the same period a client could again send a burst of ten requests and then had to wait two seconds before sending further requests or 20 seconds before the full quota would be replenished and he could send another burst.
§Example
use actix_governor::{Governor, GovernorConfigBuilder};
use actix_web::{web, App, HttpServer, Responder};
async fn index() -> impl Responder {
"Hello world!"
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
// Allow bursts with up to five requests per IP address
// and replenishes one element every two seconds
let governor_conf = GovernorConfigBuilder::default()
.seconds_per_request(2)
.burst_size(5)
.finish()
.unwrap();
HttpServer::new(move || {
App::new()
// Enable Governor middleware
.wrap(Governor::new(&governor_conf))
// Route hello world service
.route("/", web::get().to(index))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
§Configuration presets
Instead of using the configuration builder you can use predefined presets.
-
GovernorConfig::default()
: The default configuration which is suitable for most services. Allows bursts with up to eight requests and replenishes one element after 500ms, based on peer IP. -
GovernorConfig::secure()
: A default configuration for security related services. Allows bursts with up to two requests and replenishes one element after four seconds, based on peer IP.
For example the secure configuration can be used as a short version of this code:
use actix_governor::GovernorConfigBuilder;
let config = GovernorConfigBuilder::default()
.seconds_per_request(4)
.burst_size(2)
.finish()
.unwrap();
§Customize rate limiting key
By default, rate limiting is done using the peer IP address (i.e. the IP address of the HTTP client that requested your app: either your user or a reverse proxy, depending on your deployment setup). You can configure a different behavior which:
- can be useful in itself
- allows you to setup multiple instances of this middleware based on different keys (for example, if you want to apply rate limiting with different rates on IP and API keys at the same time)
This is achieved by defining a KeyExtractor and giving it to a Governor instance. Two ready-to-use key extractors are provided:
- PeerIpKeyExtractor: this is the default
- GlobalKeyExtractor: uses the same key for all incoming requests
Check out the custom_key example to see how a custom key extractor can be implemented.
§Customizing error responses
There are two errors that might occur during rate-limiting. The first error occurs when the key can’t be extracted from the request, for example when a session id is missing. The second error occurs when the rate limit is exceeded.
§The response when key-extractions fails
The response for this error is generated by the implementation of ResponseError::error_response
for KeyExtractor::KeyExtractionError.
With this method you can generate any HttpResponse
you want, for example to return json.
But it has a simplistic problem that you can’t access the request directly, but you can solve it by creating a
new
method in the struct and passing the request that is given to you is in a method KeyExtractor::extract
to it and do whatever you want with it
For most cases can simply use SimpleKeyExtractionError
to return an error.
It returns a response with the body you set in new
, type text/plain
and 500 Internal Server Error
status by default,
but you can customize the content type with set_content_type
and the status with set_status_code
.
§The response of exceeding the rate limit
The response of this error is generated by KeyExtractor::exceed_rate_limit_response
.
This method will give you a HttpResponseBuilder
and return a HttpResponse
.
This allows you to fully customize the response.
Check out the custom_key_bearer example for more information.
§Add x-ratelimit headers
By default, x-ratelimit-after
is enabled but if you want to enable x-ratelimit-limit
, x-ratelimit-whitelisted
and x-ratelimit-remaining
use use_headers
method
§Common pitfalls
Do not construct the same configuration multiple times, unless explicitly wanted! This will create an independent rate limiter for each configuration!
Instead pass the same configuration reference into Governor::new()
,
like it is described in the example.
Re-exports§
pub use governor;
Structs§
- A KeyExtractor that allow to do rate limiting for all incoming requests. This is useful if you want to hard-limit the HTTP load your app can handle.
- Governor middleware factory.
- Configuration for the Governor middleware.
- Helper struct for building a configuration for the governor middleware.
- Extractor for governor rate limit results.
- A middleware that implements rate limiting based on the governor crate.
- A KeyExtractor that uses peer IP as key. This is the default key extractor and it may no do want you want.
- A simple struct to create error, by default the status is 500 server error and content-type is plintext
Enums§
- The result of a
GovernorExtractor
.
Traits§
- Generic structure of what is needed to extract a rate-limiting key from an incoming request.