dmsc/gateway/middleware.rs
1//! Copyright © 2025-2026 Wenze Wei. All Rights Reserved.
2//!
3//! This file is part of DMSC.
4//! The DMSC 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 DMSC gateway, allowing for
23//! request processing and modification through a chain of middleware components.
24//!
25//! ## Key Components
26//!
27//! - **DMSCMiddleware**: Trait defining the middleware interface
28//! - **DMSCMiddlewareChain**: 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 dmsc::prelude::*;
46//! use std::sync::Arc;
47//!
48//! async fn example() -> DMSCResult<()> {
49//! // Create a middleware chain
50//! let mut chain = DMSCMiddlewareChain::new();
51//!
52//! // Add built-in middleware
53//! chain.add(Arc::new(DMSCLoggingMiddleware::new("info".to_string())));
54//! chain.add(Arc::new(DMSCAuthMiddleware::new("Authorization".to_string())));
55//! chain.add(Arc::new(DMSCCorsMiddleware::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 = DMSCGatewayRequest::new("GET".to_string(), "/api/v1/resource".to_string());
63//! chain.execute(&mut request).await?;
64//!
65//! Ok(())
66//! }
67//! ```
68
69use super::DMSCGatewayRequest;
70use crate::core::DMSCResult;
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 DMSCMiddleware: 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 `DMSCResult<()>` indicating success or failure
92 async fn execute(&self, request: &mut DMSCGatewayRequest) -> DMSCResult<()>;
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 DMSCMiddlewareChain {
110 /// Vector of middleware instances in the order they should be executed
111 middlewares: Vec<Arc<dyn DMSCMiddleware>>,
112}
113
114impl Default for DMSCMiddlewareChain {
115 fn default() -> Self {
116 Self::new()
117 }
118}
119
120impl DMSCMiddlewareChain {
121 /// Creates a new empty middleware chain.
122 ///
123 /// # Returns
124 ///
125 /// A new `DMSCMiddlewareChain` 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 DMSCMiddleware>) {
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 `DMSCResult<()>` indicating success or failure
153 pub async fn execute(&self, request: &mut DMSCGatewayRequest) -> DMSCResult<()> {
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 DMSCAuthMiddleware {
199 /// Name of the authorization header to check
200 auth_header: String,
201}
202
203impl DMSCAuthMiddleware {
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 `DMSCAuthMiddleware` instance
213 pub fn new(auth_header: String) -> Self {
214 Self { auth_header }
215 }
216}
217
218#[async_trait]
219impl DMSCMiddleware for DMSCAuthMiddleware {
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 `DMSCResult<()>` indicating success or failure
232 async fn execute(&self, request: &mut DMSCGatewayRequest) -> DMSCResult<()> {
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::DMSCError::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::DMSCError::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 DMSCCorsMiddleware {
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 DMSCCorsMiddleware {
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 `DMSCCorsMiddleware` 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 /// # Parameters
302 ///
303 /// - `origin`: The origin to check
304 ///
305 /// # Returns
306 ///
307 /// `true` if the origin is allowed, `false` otherwise
308 fn is_origin_allowed(&self, origin: &str) -> bool {
309 self.allowed_origins.contains(&"*".to_string()) ||
310 self.allowed_origins.iter().any(|allowed| allowed == origin)
311 }
312}
313
314#[async_trait]
315impl DMSCMiddleware for DMSCCorsMiddleware {
316 /// Validates CORS headers in the request.
317 ///
318 /// This implementation checks if the request origin is in the list of allowed origins.
319 ///
320 /// # Parameters
321 ///
322 /// - `request`: Mutable reference to the request being processed
323 ///
324 /// # Returns
325 ///
326 /// A `DMSCResult<()>` indicating success or failure
327 async fn execute(&self, request: &mut DMSCGatewayRequest) -> DMSCResult<()> {
328 // CORS preflight handling would be done at the response level
329 // This middleware just validates the request
330
331 if let Some(origin) = request.headers.get("origin") {
332 if !self.is_origin_allowed(origin) {
333 return Err(crate::core::DMSCError::Other("Origin not allowed".to_string()));
334 }
335 }
336
337 Ok(())
338 }
339
340 /// Gets the name of the middleware.
341 ///
342 /// # Returns
343 ///
344 /// The string "CorsMiddleware"
345 fn name(&self) -> &'static str {
346 "CorsMiddleware"
347 }
348}
349
350/// Logging middleware for recording request details.
351///
352/// This middleware logs request information such as method, path, and remote address.
353pub struct DMSCLoggingMiddleware {
354 /// Log level for the middleware
355 #[allow(dead_code)]
356 log_level: String,
357}
358
359impl DMSCLoggingMiddleware {
360 /// Creates a new logging middleware instance.
361 ///
362 /// # Parameters
363 ///
364 /// - `log_level`: Log level for the middleware
365 ///
366 /// # Returns
367 ///
368 /// A new `DMSCLoggingMiddleware` instance
369 pub fn new(log_level: String) -> Self {
370 Self { log_level }
371 }
372}
373
374#[async_trait]
375impl DMSCMiddleware for DMSCLoggingMiddleware {
376 /// Logs request details.
377 ///
378 /// This implementation prints request information to the console.
379 /// In a production environment, this would use a proper logging framework.
380 ///
381 /// # Parameters
382 ///
383 /// - `request`: Mutable reference to the request being processed
384 ///
385 /// # Returns
386 ///
387 /// A `DMSCResult<()>` indicating success or failure
388 async fn execute(&self, request: &mut DMSCGatewayRequest) -> DMSCResult<()> {
389 // In a real implementation, this would log the request details
390 // For now, we'll just allow it through
391 log::info!("[{}] {} {} from {}",
392 chrono::Utc::now().format("%Y-%m-%d %H:%M:%S"),
393 request.method,
394 request.path,
395 request.remote_addr
396 );
397 Ok(())
398 }
399
400 /// Gets the name of the middleware.
401 ///
402 /// # Returns
403 ///
404 /// The string "LoggingMiddleware"
405 fn name(&self) -> &'static str {
406 "LoggingMiddleware"
407 }
408}
409
410/// Request ID middleware for processing request IDs.
411///
412/// This middleware handles request ID generation and processing.
413/// Note: Request IDs are already generated in `DMSCGatewayRequest::new`.
414pub struct DMSCRequestIdMiddleware;
415
416impl Default for DMSCRequestIdMiddleware {
417 fn default() -> Self {
418 Self::new()
419 }
420}
421
422impl DMSCRequestIdMiddleware {
423 /// Creates a new request ID middleware instance.
424 ///
425 /// # Returns
426 ///
427 /// A new `DMSCRequestIdMiddleware` instance
428 pub fn new() -> Self {
429 Self
430 }
431}
432
433#[async_trait]
434impl DMSCMiddleware for DMSCRequestIdMiddleware {
435 /// Processes the request ID in the request.
436 ///
437 /// This implementation is a no-op since request IDs are generated in `DMSCGatewayRequest::new`.
438 /// It can be extended for additional request ID processing.
439 ///
440 /// # Parameters
441 ///
442 /// - `_request`: Mutable reference to the request being processed
443 ///
444 /// # Returns
445 ///
446 /// A `DMSCResult<()>` indicating success or failure
447 async fn execute(&self, _request: &mut DMSCGatewayRequest) -> DMSCResult<()> {
448 // Request ID is already generated in DMSCGatewayRequest::new
449 // This middleware can be used for additional request ID processing
450 Ok(())
451 }
452
453 /// Gets the name of the middleware.
454 ///
455 /// # Returns
456 ///
457 /// The string "RequestIdMiddleware"
458 fn name(&self) -> &'static str {
459 "RequestIdMiddleware"
460 }
461}
462
463/// Rate limiting middleware for controlling request rates.
464///
465/// This middleware limits the number of requests from a client within a specified time window.
466pub struct DMSCRateLimitMiddleware {
467 /// Rate limiter instance for enforcing rate limits
468 rate_limiter: Arc<crate::gateway::DMSCRateLimiter>,
469}
470
471impl DMSCRateLimitMiddleware {
472 /// Creates a new rate limiting middleware instance.
473 ///
474 /// # Parameters
475 ///
476 /// - `rate_limiter`: Rate limiter instance for enforcing rate limits
477 ///
478 /// # Returns
479 ///
480 /// A new `DMSCRateLimitMiddleware` instance
481 pub fn new(rate_limiter: Arc<crate::gateway::DMSCRateLimiter>) -> Self {
482 Self {
483 rate_limiter,
484 }
485 }
486}
487
488#[async_trait]
489impl DMSCMiddleware for DMSCRateLimitMiddleware {
490 /// Applies rate limiting to the request.
491 ///
492 /// This implementation uses the DMSCRateLimiter to check if the request should be allowed
493 /// based on rate limiting rules. If the request exceeds the rate limit, an error is returned.
494 ///
495 /// # Parameters
496 ///
497 /// - `request`: Mutable reference to the request being processed
498 ///
499 /// # Returns
500 ///
501 /// A `DMSCResult<()>` indicating success or failure. Returns error if rate limit exceeded.
502 async fn execute(&self, request: &mut DMSCGatewayRequest) -> DMSCResult<()> {
503 // Check rate limit using the rate limiter
504 if !self.rate_limiter.check_request(request).await {
505 return Err(crate::core::DMSCError::Other("Rate limit exceeded".to_string()));
506 }
507
508 Ok(())
509 }
510
511 /// Gets the name of the middleware.
512 ///
513 /// # Returns
514 ///
515 /// The string "RateLimitMiddleware"
516 fn name(&self) -> &'static str {
517 "RateLimitMiddleware"
518 }
519}