use std::sync::atomic::{AtomicUsize, Ordering};
use std::time::{Duration, Instant};
pub struct RateLimit {
count: AtomicUsize,
last_reset: std::sync::Mutex<Instant>,
limit: usize,
window: Duration,
}
impl RateLimit {
pub fn new(limit: usize, window: Duration) -> Self {
Self {
count: AtomicUsize::new(0),
last_reset: std::sync::Mutex::new(Instant::now()),
limit,
window,
}
}
}
#[async_trait]
impl MiddleWareHandler for RateLimit {
async fn handle(&self, req: Request, next: &Next) -> Result<Response> {
let mut last_reset = self.last_reset.lock().unwrap();
if last_reset.elapsed() >= self.window {
self.count.store(0, Ordering::SeqCst);
*last_reset = Instant::now();
}
if self.count.fetch_add(1, Ordering::SeqCst) >= self.limit {
return Err(Error::new("Too many requests")
.with_status(StatusCode::TOO_MANY_REQUESTS));
}
next.call(req).await
}
}