Expand description
This crate provides RFC 6585 compliant in-memory rate limiting with configurable windows and limits as lightweight middleware for Warp web applications.
It provides a Filter you add to your routes that exposes rate-limiting information to your handlers, and a Rejection Type for error recovery.
It does not yet provide persistence, nor is the HashMap that stores IPs bounded. Both of these may be changed in a future version.
§Quickstart
- Include the crate:
cargo add warp-rate-limit
- Define one or more rate limit configurations. Following are some examples of available builder methods. The variable names are arbitrary:
ⓘ
// Limit: 60 requests per 60 Earth seconds
let public_routes_rate_limit = RateLimitConfig::default();
// Limit: 100 requests per 60 Earth seconds
let parter_routes_rate_limit = RateLimitConfig::max_per_minute(100);
// Limit: 10 requests per 20 Earth seconds
let static_route_limit = RateLimitConfig::max_per_window(10,20);- Use rate limiting information in request handler. If you don’t want to use rate-limiting information related to the IP address associated with this request, you can skip this part.
ⓘ
// Example route handler
async fn hande_request(rate_limit_info: RateLimitInfo) -> Result<impl Reply, Rejection> {
// Create a base response
let mut response = warp::reply::with_status(
"Hello world",
StatusCode::OK
).into_response();
// Optionally add rate limit headers to your response.
if let Err(e) = add_rate_limit_headers(response.headers_mut(), &rate_limit_info) {
match e {
RateLimitError::HeaderError(e) => {
eprintln!("Failed to set rate limit headers due to invalid value: {}", e);
}
RateLimitError::Other(e) => {
eprintln!("Unexpected error setting rate limit headers: {}", e);
}
}
}
// You could also replace the above `if let Err(e)` block with:
// let _ = add_rate_limit_headers(response.headers_mut(), &rate_limit_info);
Ok(response)
}- Handle rate limit errors in your rejection handler:
ⓘ
// Example rejection handler
async fn handle_rejection(rejection: Rejection) -> Result<impl Reply, Infallible> {
// Somewhere in your rejection handling:
if let Some(rate_limit_rejection) = rejection.find::<RateLimitRejection>() {
// We have a rate limit rejection -- so let's get some info about it:
let info = get_rate_limit_info(rate_limit_rejection);
// Let's use that info to create a response:
let message = format!(
"Rate limit exceeded. Try again after {}.",
info.retry_after
);
// Let's build that response:
let mut response = warp::reply::with_status(
message,
StatusCode::TOO_MANY_REQUESTS
).into_response();
// Then, let's add the rate-limiting headers to that response:
if let Err(e) = add_rate_limit_headers(response.headers_mut(), &info) {
// Whether or not you use the specific RateLimitError in
// your handler, consider handling errors explicitly here.
// Again, though, you're free to `if let _ = add_rate_limit_headers(...`
// if you don't care about these errors.
match e {
RateLimitError::HeaderError(e) => {
eprintln!("Failed to set rate limit headers due to invalid value: {}", e);
}
RateLimitError::Other(e) => {
eprintln!("Unexpected error setting rate limit headers: {}", e);
}
}
}
Ok(response)
} else {
// Handle other types of rejections, e.g.
Ok(warp::reply::with_status(
"Internal Server Error",
StatusCode::INTERNAL_SERVER_ERROR,
).into_response())
}
} Re-exports§
Structs§
- Rate
Limit Config - Configuration for the rate limiter
- Rate
Limit Info - Information about the current rate limit status
- Rate
Limit Rejection - Custom rejection type for rate limiting
Enums§
- Rate
Limit Error - Errors that can occur during rate limiting logic
- Retry
After Format - Format options for the Retry-After header
Functions§
- add_
rate_ limit_ headers - Adds rate limit headers to a response
- get_
rate_ limit_ info - Gets rate limit information from a rejection
- with_
rate_ limit - Creates a rate limiting filter with the given configuration