Skip to main content

litellm_rs/core/traits/
middleware.rs

1//! Middleware system trait definitions
2//!
3//! Provides composable middleware architecture supporting authentication, cache, retry, and other cross-cutting concerns
4
5use async_trait::async_trait;
6use std::future::Future;
7use std::pin::Pin;
8
9/// Core middleware trait
10///
11/// All middleware must implement this trait
12#[async_trait]
13pub trait Middleware<Req, Resp>: Send + Sync {
14    /// Error
15    type Error: std::error::Error + Send + Sync + 'static;
16
17    /// Process request through middleware
18    ///
19    /// # Parameters
20    /// * `request` - Incoming request
21    /// * `next` - Next handler in the chain
22    ///
23    /// # Returns
24    /// Processed response
25    async fn process(
26        &self,
27        request: Req,
28        next: Box<dyn MiddlewareNext<Req, Resp>>,
29    ) -> Result<Resp, Self::Error>;
30}
31
32/// Next middleware handler in the chain
33#[async_trait]
34pub trait MiddlewareNext<Req, Resp>: Send + Sync {
35    /// Call the next handler in the chain
36    async fn call(&self, request: Req) -> Result<Resp, MiddlewareError>;
37}
38
39// Type aliases for cleaner types
40type BoxedMiddleware<Req, Resp> = Box<dyn Middleware<Req, Resp, Error = MiddlewareError>>;
41type BoxedFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
42
43/// Middleware chain/stack
44pub struct MiddlewareStack<Req, Resp> {
45    middlewares: Vec<BoxedMiddleware<Req, Resp>>,
46}
47
48impl<Req, Resp> MiddlewareStack<Req, Resp>
49where
50    Req: Clone + Send + Sync + 'static,
51    Resp: Send + Sync + 'static,
52{
53    /// Create new middleware stack
54    pub fn new() -> Self {
55        Self {
56            middlewares: Vec::new(),
57        }
58    }
59
60    /// Add middleware to the stack
61    pub fn add_middleware<M>(self, _middleware: M) -> Self
62    where
63        M: Middleware<Req, Resp> + 'static,
64    {
65        // NOTE: Middleware wrapper type constraints not yet resolved.
66        self
67    }
68
69    /// Execute middleware chain
70    pub async fn execute<F, Fut>(
71        &self,
72        request: Req,
73        final_handler: F,
74    ) -> Result<Resp, MiddlewareError>
75    where
76        F: FnOnce(Req) -> Fut + Send + Sync + 'static,
77        Fut: Future<Output = Result<Resp, MiddlewareError>> + Send + Sync + 'static,
78    {
79        let handler = Box::new(FinalHandler::new(final_handler));
80        self.execute_chain(request, 0, handler).await
81    }
82
83    /// Recursively execute middleware chain
84    fn execute_chain(
85        &self,
86        request: Req,
87        index: usize,
88        final_handler: Box<dyn MiddlewareNext<Req, Resp>>,
89    ) -> BoxedFuture<'_, Result<Resp, MiddlewareError>> {
90        Box::pin(async move {
91            if index >= self.middlewares.len() {
92                // Execute final handler
93                final_handler.call(request).await
94            } else {
95                // Create next handler
96                let _next = Box::new(NextHandler {
97                    _stack: self,
98                    _index: index + 1,
99                    _final_handler: final_handler,
100                    _request: request.clone(),
101                });
102
103                // NOTE: Middleware execution disabled; type constraints not yet resolved.
104                // self.middlewares[index].process(request, next).await
105                Err(MiddlewareError::ExecutionFailed(
106                    "Middleware system temporarily disabled".to_string(),
107                ))
108            }
109        })
110    }
111}
112
113impl<Req, Resp> Default for MiddlewareStack<Req, Resp>
114where
115    Req: Clone + Send + Sync + 'static,
116    Resp: Send + Sync + 'static,
117{
118    fn default() -> Self {
119        Self::new()
120    }
121}
122
123/// Final handler wrapper
124struct FinalHandler<F, Fut, Req, Resp> {
125    _handler: Option<F>,
126    _phantom: std::marker::PhantomData<(Fut, Req, Resp)>,
127}
128
129impl<F, Fut, Req, Resp> FinalHandler<F, Fut, Req, Resp> {
130    fn new(handler: F) -> Self {
131        Self {
132            _handler: Some(handler),
133            _phantom: std::marker::PhantomData,
134        }
135    }
136}
137
138#[async_trait]
139impl<F, Fut, Req, Resp> MiddlewareNext<Req, Resp> for FinalHandler<F, Fut, Req, Resp>
140where
141    F: FnOnce(Req) -> Fut + Send + Sync,
142    Fut: Future<Output = Result<Resp, MiddlewareError>> + Send + Sync,
143    Req: Send + Sync,
144    Resp: Send + Sync,
145{
146    async fn call(&self, _request: Req) -> Result<Resp, MiddlewareError> {
147        // FnOnce can only be called once, but trait methods may be called multiple times
148        // This requires a more complex design with interior mutability
149        Err(MiddlewareError::ExecutionFailed(
150            "FinalHandler: FnOnce handling not yet implemented".to_string(),
151        ))
152    }
153}
154
155/// Next handler wrapper
156struct NextHandler<'a, Req, Resp> {
157    _stack: &'a MiddlewareStack<Req, Resp>,
158    _index: usize,
159    _final_handler: Box<dyn MiddlewareNext<Req, Resp>>,
160    _request: Req,
161}
162
163#[async_trait]
164impl<'a, Req, Resp> MiddlewareNext<Req, Resp> for NextHandler<'a, Req, Resp>
165where
166    Req: Clone + Send + Sync + 'static,
167    Resp: Send + Sync + 'static,
168{
169    async fn call(&self, _request: Req) -> Result<Resp, MiddlewareError> {
170        // This requires redesign due to lifetime issues with recursive middleware chains
171        Err(MiddlewareError::ExecutionFailed(
172            "NextHandler: next handler not yet implemented".to_string(),
173        ))
174    }
175}
176
177/// Error
178#[derive(Debug, thiserror::Error)]
179pub enum MiddlewareError {
180    #[error("Middleware chain execution failed: {0}")]
181    ExecutionFailed(String),
182
183    #[error("Invalid middleware configuration: {0}")]
184    InvalidConfiguration(String),
185
186    #[error("Middleware timeout after {timeout_ms}ms")]
187    Timeout { timeout_ms: u64 },
188
189    #[error("Other middleware error: {0}")]
190    Other(String),
191}
192
193#[cfg(test)]
194mod tests {
195    use super::*;
196
197    // ==================== MiddlewareStack Tests ====================
198
199    #[test]
200    fn test_middleware_stack_new() {
201        let stack: MiddlewareStack<String, String> = MiddlewareStack::new();
202        assert!(stack.middlewares.is_empty());
203    }
204
205    #[test]
206    fn test_middleware_stack_default() {
207        let stack: MiddlewareStack<String, String> = MiddlewareStack::default();
208        assert!(stack.middlewares.is_empty());
209    }
210
211    // ==================== MiddlewareError Tests ====================
212
213    #[test]
214    fn test_middleware_error_execution_failed() {
215        let err = MiddlewareError::ExecutionFailed("Handler failed".to_string());
216        assert!(
217            err.to_string()
218                .contains("Middleware chain execution failed")
219        );
220        assert!(err.to_string().contains("Handler failed"));
221    }
222
223    #[test]
224    fn test_middleware_error_invalid_configuration() {
225        let err = MiddlewareError::InvalidConfiguration("Missing required field".to_string());
226        assert!(err.to_string().contains("Invalid middleware configuration"));
227        assert!(err.to_string().contains("Missing required field"));
228    }
229
230    #[test]
231    fn test_middleware_error_timeout() {
232        let err = MiddlewareError::Timeout { timeout_ms: 5000 };
233        assert!(err.to_string().contains("timeout"));
234        assert!(err.to_string().contains("5000"));
235    }
236
237    #[test]
238    fn test_middleware_error_other() {
239        let err = MiddlewareError::Other("Unknown error".to_string());
240        assert!(err.to_string().contains("Unknown error"));
241    }
242
243    #[test]
244    fn test_middleware_error_display() {
245        let err = MiddlewareError::ExecutionFailed("test".to_string());
246        let display = format!("{}", err);
247        assert!(!display.is_empty());
248    }
249
250    #[test]
251    fn test_middleware_error_debug() {
252        let err = MiddlewareError::Timeout { timeout_ms: 1000 };
253        let debug = format!("{:?}", err);
254        assert!(debug.contains("Timeout"));
255        assert!(debug.contains("1000"));
256    }
257}