bindcar/
rate_limit.rs

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