use std::future::Future;
use std::pin::Pin;
use axum::body::Body;
use axum::http::Request;
mod adapter;
pub use adapter::{LimiteronAdapter, LimiteronAdapterBuilder};
mod middleware;
pub use middleware::{RateLimitLayer, RateLimitMiddleware};
#[cfg(test)]
mod tests;
pub trait RateLimiter: Send + Sync {
fn check<'a>(
&'a self,
identifier: &'a str,
) -> Pin<Box<dyn Future<Output = Result<(), RateLimitError>> + Send + 'a>>;
fn check_request<'a>(
&'a self,
req: &'a Request<Body>,
) -> Pin<Box<dyn Future<Output = Result<(), RateLimitError>> + Send + 'a>>;
}
#[derive(Debug, thiserror::Error)]
pub enum RateLimitError {
#[error("Rate limit exceeded: {limit} per {window_seconds}s")]
Exceeded {
limit: u64,
window_seconds: u64,
},
#[error("Identifier banned: {reason}")]
Banned {
reason: String,
},
#[error("Circuit breaker open")]
CircuitOpen,
#[error("Quota exhausted: {used}/{total}")]
QuotaExhausted {
used: u64,
total: u64,
},
#[error("Limiteron error: {0}")]
Limiteron(#[from] limiteron::FlowGuardError),
}