use super::{BoxedMiddleware, MiddlewareFuture, Next};
use crate::http::{Request, Response};
use crate::routing::BoxedHandler;
use std::sync::Arc;
pub struct MiddlewareChain {
middleware: Vec<BoxedMiddleware>,
}
impl MiddlewareChain {
pub fn new() -> Self {
Self {
middleware: Vec::new(),
}
}
pub fn push(&mut self, middleware: BoxedMiddleware) {
self.middleware.push(middleware);
}
pub fn extend(&mut self, middleware: impl IntoIterator<Item = BoxedMiddleware>) {
self.middleware.extend(middleware);
}
pub async fn execute(self, request: Request, handler: Arc<BoxedHandler>) -> Response {
if self.middleware.is_empty() {
return handler(request).await;
}
let handler_clone = handler.clone();
let mut next: Next = Arc::new(move |req| handler_clone(req));
for middleware in self.middleware.into_iter().rev() {
let current_next = next;
let mw = middleware;
next = Arc::new(move |req| {
let n = current_next.clone();
let m = mw.clone();
Box::pin(async move { m(req, n).await }) as MiddlewareFuture
});
}
next(request).await
}
}
impl Default for MiddlewareChain {
fn default() -> Self {
Self::new()
}
}