#[cfg(test)]
mod tests;
use std::sync::Arc;
use crate::application::Application;
use crate::request::Request;
use crate::response::Response;
use crate::server::ConnectionInfo;
pub struct RateLimitLayer;
impl Middleware for RateLimitLayer {
fn handle(
&self,
request: &Request,
connection: &ConnectionInfo,
next: &dyn Application,
) -> Result<Response, String> {
use crate::error::{AppError, IntoResponse};
if crate::rate_limit::global().check(&connection.client.ip) {
next.execute(request, connection)
} else {
Ok(AppError::TooManyRequests.into_response())
}
}
}
pub trait Middleware: Send + Sync {
fn handle(
&self,
request: &Request,
connection: &ConnectionInfo,
next: &dyn Application,
) -> Result<Response, String>;
}
pub struct WithMiddleware<A> {
inner: A,
layers: Vec<Arc<dyn Middleware>>,
}
impl<A: Application> WithMiddleware<A> {
pub fn new(app: A) -> Self {
WithMiddleware { inner: app, layers: Vec::new() }
}
pub fn wrap(mut self, layer: impl Middleware + 'static) -> Self {
self.layers.push(Arc::new(layer));
self
}
}
impl<A: Application + Send + Sync + Clone + 'static> WithMiddleware<A> {
pub fn mcp(self, name: impl Into<String>, version: impl Into<String>) -> crate::mcp::McpServer {
crate::mcp::McpServer::new(name, version).wrap(self)
}
}
impl<A: Clone> Clone for WithMiddleware<A> {
fn clone(&self) -> Self {
WithMiddleware { inner: self.inner.clone(), layers: self.layers.clone() }
}
}
impl<A: Application> Application for WithMiddleware<A> {
fn execute(&self, request: &Request, connection: &ConnectionInfo) -> Result<Response, String> {
Chain { app: &self.inner, layers: &self.layers, index: 0 }.execute(request, connection)
}
}
struct Chain<'a> {
app: &'a dyn Application,
layers: &'a [Arc<dyn Middleware>],
index: usize,
}
impl<'a> Application for Chain<'a> {
fn execute(&self, request: &Request, connection: &ConnectionInfo) -> Result<Response, String> {
if self.index < self.layers.len() {
let next = Chain { app: self.app, layers: self.layers, index: self.index + 1 };
self.layers[self.index].handle(request, connection, &next)
} else {
self.app.execute(request, connection)
}
}
}