Expand description
A simple and highly customizable rate limiting middleware for actix-web 4.
For complete documentation and examples, visit the GitHub repository.
§Features
- actix-web 4 Compatible: Built specifically for actix-web 4
- Simple & Easy to Use: Minimal configuration required
- Pluggable Storage: Support for in-memory and Redis storage backends
- High Performance: Efficient sliding window algorithm
- Customizable: Custom client identification and rate limit exceeded handlers
- Thread Safe: Concurrent request handling with DashMap
§Quick Start
Add this to your Cargo.toml:
[dependencies]
actix-web-ratelimit = "0.1"
# Or, for Redis support
actix-web-ratelimit = { version = "0.1", features = ["redis"] }§Usage
§Basic Usage with In-Memory Store
// Configure rate limiting: allow 3 requests per 10-second window
let config = RateLimitConfig::default().max_requests(3).window_secs(10);
// Create in-memory store for tracking request timestamps
let store = Arc::new(MemoryStore::new());
HttpServer::new(move || {
App::new()
// Create and register the rate limit middleware.
.wrap(RateLimit::new(config.clone(), store.clone()))
.route("/", web::get().to(index))
})
.bind(("127.0.0.1", 8080))?
.run()
.await§Advanced Configuration
let store = Arc::new(MemoryStore::new());
let config = RateLimitConfig::default()
.max_requests(3)
.window_secs(10)
// Extract client identifier from req. It is IP (realip_remote_addr) by default.
.id(|req| {
req.headers()
.get("X-Client-Id")
.and_then(|h| h.to_str().ok())
.unwrap_or("anonymous")
.to_string()
})
// Custom handler for rate limit exceeded. It returns a 429 response by default.
.exceeded(|id, config, _req| {
HttpResponse::TooManyRequests().body(format!(
"429 caused: client-id: {}, limit: {}req/{:?}",
id, config.max_requests, config.window_secs
))
});
HttpServer::new(move || {
App::new()
.wrap(RateLimit::new(config.clone(), store.clone()))
.route("/", web::get().to(index))
})
.bind(("127.0.0.1", 8080))?
.run()
.await§Redis Store
First, enable the redis feature:
[dependencies]
actix-web-ratelimit = { version = "0.1", features = ["redis"] }Then you can use Redis as the storage backend:
let store = Arc::new(
RedisStore::new("redis://127.0.0.1/0")
.expect("Failed to connect to Redis")
// Custom prefix for Redis keys
.with_prefix("myapp:ratelimit:"),
);
let config = RateLimitConfig::default().max_requests(3).window_secs(10);
HttpServer::new(move || {
App::new()
.wrap(RateLimit::new(config.clone(), store.clone()))
.route("/", web::get().to(index))
})
.bind(("127.0.0.1", 8080))?
.run()
.await
§Storage Backends
This crate provides two built-in storage implementations:
store::MemoryStore- In-memory storage usingdashmap::DashMapstore::RedisStore- Distributed storage using Redis (requiresredisfeature)
For custom storage backends, implement the store::RateLimitStore trait.
§Configuration
Rate limiting behavior is controlled by config::RateLimitConfig:
max_requests- Maximum requests allowed within the time windowwindow_secs- Duration of the sliding time window in secondsget_id- Function to extract client identifier from requestson_exceed- Function called when rate limit is exceeded