kit_rs/middleware/
mod.rs

1//! Middleware system for Kit framework
2//!
3//! This module provides Laravel 12.x-style middleware support with:
4//! - Global middleware (runs on all routes)
5//! - Route group middleware (shared for a group of routes)
6//! - Per-route middleware (applied to individual routes)
7//!
8//! # Example
9//!
10//! ```rust,ignore
11//! use kit::{async_trait, Middleware, Next, Request, Response, HttpResponse};
12//!
13//! pub struct AuthMiddleware;
14//!
15//! #[async_trait]
16//! impl Middleware for AuthMiddleware {
17//!     async fn handle(&self, request: Request, next: Next) -> Response {
18//!         if request.header("Authorization").is_none() {
19//!             return Err(HttpResponse::text("Unauthorized").status(401));
20//!         }
21//!         next(request).await
22//!     }
23//! }
24//! ```
25
26mod chain;
27mod registry;
28
29pub use chain::MiddlewareChain;
30pub use registry::MiddlewareRegistry;
31
32use crate::http::{Request, Response};
33use async_trait::async_trait;
34use std::future::Future;
35use std::pin::Pin;
36use std::sync::Arc;
37
38/// Type alias for the boxed future returned by middleware
39pub type MiddlewareFuture = Pin<Box<dyn Future<Output = Response> + Send>>;
40
41/// Type alias for the next handler in the middleware chain
42///
43/// Call `next(request).await` to pass control to the next middleware or the route handler.
44pub type Next = Arc<dyn Fn(Request) -> MiddlewareFuture + Send + Sync>;
45
46/// Type alias for boxed middleware handlers (internal use)
47pub type BoxedMiddleware = Arc<dyn Fn(Request, Next) -> MiddlewareFuture + Send + Sync>;
48
49/// Trait for implementing middleware
50///
51/// Middleware can inspect/modify requests, short-circuit responses, or pass control
52/// to the next middleware in the chain by calling `next(request).await`.
53///
54/// # Example
55///
56/// ```rust,ignore
57/// use kit::{async_trait, Middleware, Next, Request, Response, HttpResponse};
58///
59/// pub struct LoggingMiddleware;
60///
61/// #[async_trait]
62/// impl Middleware for LoggingMiddleware {
63///     async fn handle(&self, request: Request, next: Next) -> Response {
64///         println!("--> {} {}", request.method(), request.path());
65///         let response = next(request).await;
66///         println!("<-- complete");
67///         response
68///     }
69/// }
70/// ```
71#[async_trait]
72pub trait Middleware: Send + Sync {
73    /// Handle the request
74    ///
75    /// - Call `next(request).await` to pass control to the next middleware
76    /// - Return `Err(HttpResponse)` to short-circuit and respond immediately
77    /// - Modify the response after calling `next()` for post-processing
78    async fn handle(&self, request: Request, next: Next) -> Response;
79}
80
81/// Convert a Middleware trait object into a BoxedMiddleware
82pub fn into_boxed<M: Middleware + 'static>(middleware: M) -> BoxedMiddleware {
83    let middleware = Arc::new(middleware);
84    Arc::new(move |req, next| {
85        let mw = middleware.clone();
86        Box::pin(async move { mw.handle(req, next).await })
87    })
88}