kit_rs/middleware/chain.rs
1//! Middleware chain execution engine
2
3use super::{BoxedMiddleware, MiddlewareFuture, Next};
4use crate::http::{Request, Response};
5use crate::routing::BoxedHandler;
6use std::sync::Arc;
7
8/// Builds and executes the middleware chain
9///
10/// The chain is built from the outside-in:
11/// 1. Global middleware (first to run)
12/// 2. Route group middleware
13/// 3. Route-level middleware
14/// 4. The actual route handler (innermost)
15pub struct MiddlewareChain {
16 middleware: Vec<BoxedMiddleware>,
17}
18
19impl MiddlewareChain {
20 /// Create a new empty middleware chain
21 pub fn new() -> Self {
22 Self {
23 middleware: Vec::new(),
24 }
25 }
26
27 /// Add middleware to the chain
28 ///
29 /// Middleware are executed in the order they are added.
30 pub fn push(&mut self, middleware: BoxedMiddleware) {
31 self.middleware.push(middleware);
32 }
33
34 /// Add multiple middleware to the chain
35 pub fn extend(&mut self, middleware: impl IntoIterator<Item = BoxedMiddleware>) {
36 self.middleware.extend(middleware);
37 }
38
39 /// Execute the middleware chain with the given request and final handler
40 ///
41 /// The chain is executed from outside-in:
42 /// - First middleware added runs first
43 /// - Each middleware can call `next(request)` to continue the chain
44 /// - The final handler is called at the end of the chain
45 pub async fn execute(self, request: Request, handler: Arc<BoxedHandler>) -> Response {
46 if self.middleware.is_empty() {
47 // No middleware - call handler directly
48 return handler(request).await;
49 }
50
51 // Build the chain from inside-out
52 // Start with the actual handler as the innermost "next"
53 let handler_clone = handler.clone();
54 let mut next: Next = Arc::new(move |req| handler_clone(req));
55
56 // Wrap each middleware around the next, from last to first
57 // This creates the correct execution order: first middleware runs first
58 for middleware in self.middleware.into_iter().rev() {
59 let current_next = next;
60 let mw = middleware;
61 next = Arc::new(move |req| {
62 let n = current_next.clone();
63 let m = mw.clone();
64 Box::pin(async move { m(req, n).await }) as MiddlewareFuture
65 });
66 }
67
68 // Execute the outermost middleware (which was the first added)
69 next(request).await
70 }
71}
72
73impl Default for MiddlewareChain {
74 fn default() -> Self {
75 Self::new()
76 }
77}