1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
//! Rate limiting middleware for HTTP requests
//!
//! This module provides rate limiting functionality using the tower-governor crate,
//! which implements the Generic Cell Rate Algorithm (GCRA). Rate limits are
//! keyed on the real TCP peer IP ([`PeerIpKeyExtractor`]) rather than the
//! spoofable `X-Forwarded-For` family of headers, so a client cannot evade the
//! limit or exhaust another client's bucket by forging a forwarding header.
// Re-export commonly used types for convenience
pub use tower_governor::{
governor::GovernorConfigBuilder, key_extractor::PeerIpKeyExtractor, GovernorLayer,
};
/// Rate limiting configuration
#[derive(Debug, Clone)]
pub struct RateLimitConfig {
/// Maximum requests per period
pub requests_per_period: u32,
/// Period duration in seconds
pub period_secs: u64,
/// Burst size (max requests at once)
pub burst_size: u32,
/// Whether rate limiting is enabled
pub enabled: bool,
}
impl Default for RateLimitConfig {
fn default() -> Self {
Self {
requests_per_period: 100,
period_secs: 60,
burst_size: 10,
enabled: true,
}
}
}
impl RateLimitConfig {
/// Create configuration from environment variables
///
/// Environment variables:
/// - `RATE_LIMIT_ENABLED`: Enable/disable rate limiting (default: true)
/// - `RATE_LIMIT_REQUESTS`: Max requests per period (default: 100)
/// - `RATE_LIMIT_PERIOD_SECS`: Period in seconds (default: 60)
/// - `RATE_LIMIT_BURST`: Burst size (default: 10)
pub fn from_env() -> Self {
let enabled = std::env::var("RATE_LIMIT_ENABLED")
.ok()
.and_then(|v| v.parse().ok())
.unwrap_or(true);
let requests_per_period = std::env::var("RATE_LIMIT_REQUESTS")
.ok()
.and_then(|v| v.parse().ok())
.unwrap_or(100);
let period_secs = std::env::var("RATE_LIMIT_PERIOD_SECS")
.ok()
.and_then(|v| v.parse().ok())
.unwrap_or(60);
let burst_size = std::env::var("RATE_LIMIT_BURST")
.ok()
.and_then(|v| v.parse().ok())
.unwrap_or(10);
Self {
requests_per_period,
period_secs,
burst_size,
enabled,
}
}
/// Validate configuration values
pub fn validate(&self) -> Result<(), String> {
if self.requests_per_period == 0 {
return Err("requests_per_period must be greater than 0".to_string());
}
if self.period_secs == 0 {
return Err("period_secs must be greater than 0".to_string());
}
if self.burst_size == 0 {
return Err("burst_size must be greater than 0".to_string());
}
Ok(())
}
}