use axum::{
Router,
extract::{Path, State},
http::StatusCode,
routing::get,
};
use quota::{QuotaPolicy, QuotaPool, RefillRate};
use std::{net::SocketAddr, sync::Arc};
type Limiter = Arc<QuotaPool<String>>;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let policy = QuotaPolicy::new()
.set_capacity(10.0)
.set_refill_rate(RefillRate::per_sec(1));
let limiter = Arc::new(QuotaPool::new(policy, 10));
let app = Router::new()
.route("/{key}", get(limit))
.with_state(limiter);
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
axum::serve(tokio::net::TcpListener::bind(addr).await?, app).await?;
Ok(())
}
async fn limit(State(limiter): State<Limiter>, Path(key): Path<String>) -> StatusCode {
match limiter.consume(key.as_str(), 1) {
Ok(_) => StatusCode::OK,
Err(_) => StatusCode::TOO_MANY_REQUESTS,
}
}