ri/gateway/middleware.rs
1//! Copyright © 2025-2026 Wenze Wei. All Rights Reserved.
2//!
3//! This file is part of Ri.
4//! The Ri project belongs to the Dunimd Team.
5//!
6//! Licensed under the Apache License, Version 2.0 (the "License");
7//! You may not use this file except in compliance with the License.
8//! You may obtain a copy of the License at
9//!
10//! http://www.apache.org/licenses/LICENSE-2.0
11//!
12//! Unless required by applicable law or agreed to in writing, software
13//! distributed under the License is distributed on an "AS IS" BASIS,
14//! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15//! See the License for the specific language governing permissions and
16//! limitations under the License.
17
18#![allow(non_snake_case)]
19
20//! # Middleware Module
21//!
22//! This module provides a flexible middleware system for the Ri gateway, allowing for
23//! request processing and modification through a chain of middleware components.
24//!
25//! ## Key Components
26//!
27//! - **RiMiddleware**: Trait defining the middleware interface
28//! - **RiMiddlewareChain**: Manages a chain of middleware components
29//! - **Built-in Middleware**: Auth, CORS, Logging, Request ID, and Rate Limiting implementations
30//!
31//! ## Design Principles
32//!
33//! 1. **Async Trait**: Uses async_trait for async middleware execution
34//! 2. **Flexible Chain**: Allows dynamic addition and removal of middleware
35//! 3. **Extensible**: Easy to implement custom middleware
36//! 4. **Thread Safe**: Uses Arc for safe sharing of middleware instances
37//! 5. **Modular**: Built-in middleware implementations can be used independently
38//! 6. **Request Modification**: Middleware can modify requests before they reach the target service
39//! 7. **Error Handling**: Middleware can return errors to abort request processing
40//! 8. **Order Matters**: Middleware is executed in the order they are added to the chain
41//!
42//! ## Usage
43//!
44//! ```rust
45//! use ri::prelude::*;
46//! use std::sync::Arc;
47//!
48//! async fn example() -> RiResult<()> {
49//! // Create a middleware chain
50//! let mut chain = RiMiddlewareChain::new();
51//!
52//! // Add built-in middleware
53//! chain.add(Arc::new(RiLoggingMiddleware::new("info".to_string())));
54//! chain.add(Arc::new(RiAuthMiddleware::new("Authorization".to_string())));
55//! chain.add(Arc::new(RiCorsMiddleware::new(
56//! vec!["*".to_string()],
57//! vec!["GET".to_string(), "POST".to_string()],
58//! vec!["Content-Type".to_string(), "Authorization".to_string()]
59//! )));
60//!
61//! // Create a request and execute the middleware chain
62//! let mut request = RiGatewayRequest::new("GET".to_string(), "/api/v1/resource".to_string());
63//! chain.execute(&mut request).await?;
64//!
65//! Ok(())
66//! }
67//! ```
68
69use super::RiGatewayRequest;
70use crate::core::RiResult;
71use async_trait::async_trait;
72use std::sync::Arc;
73
74/// Trait defining the middleware interface for request processing.
75///
76/// All middleware components must implement this trait, which provides methods for
77/// executing middleware logic and identifying the middleware.
78#[async_trait]
79pub trait RiMiddleware: Send + Sync {
80 /// Executes the middleware logic on a request.
81 ///
82 /// This method is called for each request passing through the middleware chain.
83 /// Middleware can modify the request, validate it, or return an error to abort processing.
84 ///
85 /// # Parameters
86 ///
87 /// - `request`: Mutable reference to the request being processed
88 ///
89 /// # Returns
90 ///
91 /// A `RiResult<()>` indicating success or failure
92 async fn execute(&self, request: &mut RiGatewayRequest) -> RiResult<()>;
93
94 /// Gets the name of the middleware.
95 ///
96 /// This method returns a static string identifier for the middleware, useful for logging
97 /// and debugging purposes.
98 ///
99 /// # Returns
100 ///
101 /// A static string containing the middleware name
102 fn name(&self) -> &'static str;
103}
104
105/// Manages a chain of middleware components.
106///
107/// This struct maintains a list of middleware instances and provides methods for
108/// adding, removing, and executing middleware in sequence.
109pub struct RiMiddlewareChain {
110 /// Vector of middleware instances in the order they should be executed
111 middlewares: Vec<Arc<dyn RiMiddleware>>,
112}
113
114impl Default for RiMiddlewareChain {
115 fn default() -> Self {
116 Self::new()
117 }
118}
119
120impl RiMiddlewareChain {
121 /// Creates a new empty middleware chain.
122 ///
123 /// # Returns
124 ///
125 /// A new `RiMiddlewareChain` instance with no middleware
126 pub fn new() -> Self {
127 Self {
128 middlewares: Vec::new(),
129 }
130 }
131
132 /// Adds a middleware to the end of the chain.
133 ///
134 /// # Parameters
135 ///
136 /// - `middleware`: The middleware to add to the chain
137 pub fn add(&mut self, middleware: Arc<dyn RiMiddleware>) {
138 self.middlewares.push(middleware);
139 }
140
141 /// Executes all middleware in the chain on a request.
142 ///
143 /// Middleware is executed in the order they were added to the chain.
144 /// If any middleware returns an error, execution stops and the error is returned.
145 ///
146 /// # Parameters
147 ///
148 /// - `request`: Mutable reference to the request being processed
149 ///
150 /// # Returns
151 ///
152 /// A `RiResult<()>` indicating success or failure
153 pub async fn execute(&self, request: &mut RiGatewayRequest) -> RiResult<()> {
154 for middleware in &self.middlewares {
155 // Record middleware execution time
156 let start = std::time::Instant::now();
157
158 middleware.execute(request).await?;
159
160 let duration = start.elapsed();
161 let _duration_ms = duration.as_secs_f64() * 1000.0;
162
163 // Middleware execution time is tracked by the observability module
164 // The metrics are automatically collected when the observability feature is enabled
165 }
166 Ok(())
167 }
168
169 /// Clears all middleware from the chain.
170 pub fn clear(&mut self) {
171 self.middlewares.clear();
172 }
173
174 /// Gets the number of middleware in the chain.
175 ///
176 /// # Returns
177 ///
178 /// The number of middleware in the chain
179 pub fn len(&self) -> usize {
180 self.middlewares.len()
181 }
182
183 /// Checks if the middleware chain is empty.
184 ///
185 /// # Returns
186 ///
187 /// `true` if the chain contains no middleware, `false` otherwise
188 pub fn is_empty(&self) -> bool {
189 self.middlewares.is_empty()
190 }
191}
192
193// Built-in middleware implementations
194
195/// Authentication middleware for validating request credentials.
196///
197/// This middleware checks for and validates authorization headers in requests.
198pub struct RiAuthMiddleware {
199 /// Name of the authorization header to check
200 auth_header: String,
201}
202
203impl RiAuthMiddleware {
204 /// Creates a new authentication middleware instance.
205 ///
206 /// # Parameters
207 ///
208 /// - `auth_header`: Name of the authorization header to check
209 ///
210 /// # Returns
211 ///
212 /// A new `RiAuthMiddleware` instance
213 pub fn new(auth_header: String) -> Self {
214 Self { auth_header }
215 }
216}
217
218#[async_trait]
219impl RiMiddleware for RiAuthMiddleware {
220 /// Validates the authorization header in the request.
221 ///
222 /// This implementation checks for a Bearer token in the specified authorization header.
223 /// In a production environment, this would validate JWT tokens using the auth module.
224 ///
225 /// # Parameters
226 ///
227 /// - `request`: Mutable reference to the request being processed
228 ///
229 /// # Returns
230 ///
231 /// A `RiResult<()>` indicating success or failure
232 async fn execute(&self, request: &mut RiGatewayRequest) -> RiResult<()> {
233 // Check for authorization header
234 if let Some(auth_header) = request.headers.get(&self.auth_header) {
235 // Basic auth validation - in a real implementation, this would validate JWT tokens
236 if let Some(token) = auth_header.strip_prefix("Bearer ") {
237 if token.is_empty() {
238 return Err(crate::core::RiError::Other("Empty bearer token".to_string()));
239 }
240 // Here you would validate the JWT token using your auth module
241 } else {
242 return Err(crate::core::RiError::Other("Invalid authorization header format".to_string()));
243 }
244 } else {
245 // Allow requests without auth for public endpoints
246 // In a real implementation, you'd check if the route requires authentication
247 }
248 Ok(())
249 }
250
251 /// Gets the name of the middleware.
252 ///
253 /// # Returns
254 ///
255 /// The string "AuthMiddleware"
256 fn name(&self) -> &'static str {
257 "AuthMiddleware"
258 }
259}
260
261/// CORS (Cross-Origin Resource Sharing) middleware.
262///
263/// This middleware validates CORS headers and ensures requests come from allowed origins.
264pub struct RiCorsMiddleware {
265 /// List of allowed origins for CORS requests
266 allowed_origins: Vec<String>,
267 /// List of allowed HTTP methods for CORS requests
268 #[allow(dead_code)]
269 allowed_methods: Vec<String>,
270 /// List of allowed headers for CORS requests
271 #[allow(dead_code)]
272 allowed_headers: Vec<String>,
273}
274
275impl RiCorsMiddleware {
276 /// Creates a new CORS middleware instance.
277 ///
278 /// # Parameters
279 ///
280 /// - `allowed_origins`: List of allowed origins for CORS requests
281 /// - `allowed_methods`: List of allowed HTTP methods for CORS requests
282 /// - `allowed_headers`: List of allowed headers for CORS requests
283 ///
284 /// # Returns
285 ///
286 /// A new `RiCorsMiddleware` instance
287 pub fn new(
288 allowed_origins: Vec<String>,
289 allowed_methods: Vec<String>,
290 allowed_headers: Vec<String>,
291 ) -> Self {
292 Self {
293 allowed_origins,
294 allowed_methods,
295 allowed_headers,
296 }
297 }
298
299 /// Checks if an origin is allowed.
300 ///
301 /// # Security Note
302 ///
303 /// Wildcard origin "*" is NOT treated as matching any origin here.
304 /// Wildcard handling is done at the response header level, not validation level.
305 /// This prevents bypass attacks where any origin is falsely considered valid.
306 ///
307 /// # Parameters
308 ///
309 /// - `origin`: The origin to check
310 ///
311 /// # Returns
312 ///
313 /// `true` if the origin is allowed, `false` otherwise
314 fn is_origin_allowed(&self, origin: &str) -> bool {
315 // Wildcard should never match specific origins - it's only for response headers
316 if self.allowed_origins.contains(&"*".to_string()) {
317 // If wildcard is set, only exact matches or the wildcard itself is valid
318 // But we don't treat wildcard as matching everything
319 return false;
320 }
321 self.allowed_origins.iter().any(|allowed| allowed == origin)
322 }
323
324 /// Checks if wildcard origin is configured.
325 ///
326 /// # Returns
327 ///
328 /// `true` if wildcard origin is allowed
329 fn is_wildcard_allowed(&self) -> bool {
330 self.allowed_origins.contains(&"*".to_string())
331 }
332}
333
334#[async_trait]
335impl RiMiddleware for RiCorsMiddleware {
336 /// Validates CORS headers in the request.
337 ///
338 /// This implementation checks if the request origin is in the list of allowed origins.
339 /// If wildcard is configured, any origin is allowed but will be handled at response time.
340 ///
341 /// # Parameters
342 ///
343 /// - `request`: Mutable reference to the request being processed
344 ///
345 /// # Returns
346 ///
347 /// A `RiResult<()>` indicating success or failure
348 async fn execute(&self, request: &mut RiGatewayRequest) -> RiResult<()> {
349 // CORS preflight handling would be done at the response level
350 // This middleware just validates the request
351
352 if let Some(origin) = request.headers.get("origin") {
353 // If wildcard is allowed, origin validation passes here
354 // Actual wildcard response will be handled at response header level
355 if !self.is_wildcard_allowed() && !self.is_origin_allowed(origin) {
356 return Err(crate::core::RiError::Other("Origin not allowed".to_string()));
357 }
358 }
359
360 Ok(())
361 }
362
363 /// Gets the name of the middleware.
364 ///
365 /// # Returns
366 ///
367 /// The string "CorsMiddleware"
368 fn name(&self) -> &'static str {
369 "CorsMiddleware"
370 }
371}
372
373/// Logging middleware for recording request details.
374///
375/// This middleware logs request information such as method, path, and remote address.
376pub struct RiLoggingMiddleware {
377 /// Log level for the middleware
378 #[allow(dead_code)]
379 log_level: String,
380}
381
382impl RiLoggingMiddleware {
383 /// Creates a new logging middleware instance.
384 ///
385 /// # Parameters
386 ///
387 /// - `log_level`: Log level for the middleware
388 ///
389 /// # Returns
390 ///
391 /// A new `RiLoggingMiddleware` instance
392 pub fn new(log_level: String) -> Self {
393 Self { log_level }
394 }
395}
396
397#[async_trait]
398impl RiMiddleware for RiLoggingMiddleware {
399 /// Logs request details.
400 ///
401 /// This implementation prints request information to the console.
402 /// In a production environment, this would use a proper logging framework.
403 ///
404 /// # Parameters
405 ///
406 /// - `request`: Mutable reference to the request being processed
407 ///
408 /// # Returns
409 ///
410 /// A `RiResult<()>` indicating success or failure
411 async fn execute(&self, request: &mut RiGatewayRequest) -> RiResult<()> {
412 // In a real implementation, this would log the request details
413 // For now, we'll just allow it through
414 log::info!("[{}] {} {} from {}",
415 chrono::Utc::now().format("%Y-%m-%d %H:%M:%S"),
416 request.method,
417 request.path,
418 request.remote_addr
419 );
420 Ok(())
421 }
422
423 /// Gets the name of the middleware.
424 ///
425 /// # Returns
426 ///
427 /// The string "LoggingMiddleware"
428 fn name(&self) -> &'static str {
429 "LoggingMiddleware"
430 }
431}
432
433/// Request ID middleware for processing request IDs.
434///
435/// This middleware handles request ID generation and processing.
436/// Note: Request IDs are already generated in `RiGatewayRequest::new`.
437pub struct RiRequestIdMiddleware;
438
439impl Default for RiRequestIdMiddleware {
440 fn default() -> Self {
441 Self::new()
442 }
443}
444
445impl RiRequestIdMiddleware {
446 /// Creates a new request ID middleware instance.
447 ///
448 /// # Returns
449 ///
450 /// A new `RiRequestIdMiddleware` instance
451 pub fn new() -> Self {
452 Self
453 }
454}
455
456#[async_trait]
457impl RiMiddleware for RiRequestIdMiddleware {
458 /// Processes the request ID in the request.
459 ///
460 /// This implementation is a no-op since request IDs are generated in `RiGatewayRequest::new`.
461 /// It can be extended for additional request ID processing.
462 ///
463 /// # Parameters
464 ///
465 /// - `_request`: Mutable reference to the request being processed
466 ///
467 /// # Returns
468 ///
469 /// A `RiResult<()>` indicating success or failure
470 async fn execute(&self, _request: &mut RiGatewayRequest) -> RiResult<()> {
471 // Request ID is already generated in RiGatewayRequest::new
472 // This middleware can be used for additional request ID processing
473 Ok(())
474 }
475
476 /// Gets the name of the middleware.
477 ///
478 /// # Returns
479 ///
480 /// The string "RequestIdMiddleware"
481 fn name(&self) -> &'static str {
482 "RequestIdMiddleware"
483 }
484}
485
486/// Rate limiting middleware for controlling request rates.
487///
488/// This middleware limits the number of requests from a client within a specified time window.
489pub struct RiRateLimitMiddleware {
490 /// Rate limiter instance for enforcing rate limits
491 rate_limiter: Arc<crate::gateway::RiRateLimiter>,
492}
493
494impl RiRateLimitMiddleware {
495 /// Creates a new rate limiting middleware instance.
496 ///
497 /// # Parameters
498 ///
499 /// - `rate_limiter`: Rate limiter instance for enforcing rate limits
500 ///
501 /// # Returns
502 ///
503 /// A new `RiRateLimitMiddleware` instance
504 pub fn new(rate_limiter: Arc<crate::gateway::RiRateLimiter>) -> Self {
505 Self {
506 rate_limiter,
507 }
508 }
509}
510
511#[async_trait]
512impl RiMiddleware for RiRateLimitMiddleware {
513 /// Applies rate limiting to the request.
514 ///
515 /// This implementation uses the RiRateLimiter to check if the request should be allowed
516 /// based on rate limiting rules. If the request exceeds the rate limit, an error is returned.
517 ///
518 /// # Parameters
519 ///
520 /// - `request`: Mutable reference to the request being processed
521 ///
522 /// # Returns
523 ///
524 /// A `RiResult<()>` indicating success or failure. Returns error if rate limit exceeded.
525 async fn execute(&self, request: &mut RiGatewayRequest) -> RiResult<()> {
526 // Check rate limit using the rate limiter
527 if !self.rate_limiter.check_request(request).await {
528 return Err(crate::core::RiError::Other("Rate limit exceeded".to_string()));
529 }
530
531 Ok(())
532 }
533
534 /// Gets the name of the middleware.
535 ///
536 /// # Returns
537 ///
538 /// The string "RateLimitMiddleware"
539 fn name(&self) -> &'static str {
540 "RateLimitMiddleware"
541 }
542}