Skip to main content

pmcp/shared/
middleware.rs

1//! Advanced middleware support for request/response processing.
2//!
3//! PMCP-4004: Enhanced transport middleware system with advanced capabilities:
4//! - Rate limiting and circuit breaker patterns
5//! - Metrics collection and performance monitoring
6//! - Conditional middleware execution
7//! - Priority-based middleware ordering
8//! - Compression and caching middleware
9//! - Context propagation across middleware layers
10
11use crate::error::Result;
12use crate::shared::TransportMessage;
13use crate::types::{JSONRPCNotification, JSONRPCRequest, JSONRPCResponse};
14use async_trait::async_trait;
15use dashmap::DashMap;
16use parking_lot::RwLock;
17use std::fmt;
18use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering};
19use std::sync::Arc;
20use std::time::Duration;
21// Wasm-safe monotonic clock: `web_time::Instant` re-exports `std::time::Instant` on
22// native targets and is backed by `performance.now()` on wasm32. `std::time::Instant`
23// panics on wasm ("time not implemented on this platform"), which would abort every
24// `Client::send_request` since it stamps `MiddlewareContext::start_time`.
25use web_time::Instant;
26
27/// Execution context for middleware chains with performance tracking.
28#[derive(Debug, Clone)]
29pub struct MiddlewareContext {
30    /// Request ID for correlation
31    pub request_id: Option<String>,
32    /// Custom metadata that can be passed between middleware
33    pub metadata: Arc<DashMap<String, String>>,
34    /// Performance metrics for the request
35    pub metrics: Arc<PerformanceMetrics>,
36    /// Start time of the middleware chain execution
37    pub start_time: Instant,
38    /// Priority level for the request
39    pub priority: Option<crate::shared::transport::MessagePriority>,
40}
41
42impl Default for MiddlewareContext {
43    fn default() -> Self {
44        Self {
45            request_id: None,
46            metadata: Arc::new(DashMap::new()),
47            metrics: Arc::new(PerformanceMetrics::new()),
48            start_time: Instant::now(),
49            priority: None,
50        }
51    }
52}
53
54impl MiddlewareContext {
55    /// Create a new context with request ID
56    pub fn with_request_id(request_id: String) -> Self {
57        Self {
58            request_id: Some(request_id),
59            ..Default::default()
60        }
61    }
62
63    /// Set metadata value
64    pub fn set_metadata(&self, key: String, value: String) {
65        self.metadata.insert(key, value);
66    }
67
68    /// Get metadata value
69    pub fn get_metadata(&self, key: &str) -> Option<String> {
70        self.metadata.get(key).map(|v| v.clone())
71    }
72
73    /// Record a metric
74    pub fn record_metric(&self, name: String, value: f64) {
75        self.metrics.record(name, value);
76    }
77
78    /// Get elapsed time since context creation
79    pub fn elapsed(&self) -> Duration {
80        self.start_time.elapsed()
81    }
82}
83
84/// Performance metrics collection for middleware operations.
85#[derive(Debug, Default)]
86pub struct PerformanceMetrics {
87    /// Custom metrics storage
88    metrics: DashMap<String, f64>,
89    /// Request count
90    request_count: AtomicU64,
91    /// Error count
92    error_count: AtomicU64,
93    /// Total processing time in microseconds
94    total_time_us: AtomicU64,
95}
96
97impl PerformanceMetrics {
98    /// Create new performance metrics
99    pub fn new() -> Self {
100        Self::default()
101    }
102
103    /// Record a custom metric
104    pub fn record(&self, name: String, value: f64) {
105        self.metrics.insert(name, value);
106    }
107
108    /// Get a metric value
109    pub fn get(&self, name: &str) -> Option<f64> {
110        self.metrics.get(name).map(|v| *v)
111    }
112
113    /// Increment request count
114    pub fn inc_requests(&self) {
115        self.request_count.fetch_add(1, Ordering::Relaxed);
116    }
117
118    /// Increment error count
119    pub fn inc_errors(&self) {
120        self.error_count.fetch_add(1, Ordering::Relaxed);
121    }
122
123    /// Add processing time
124    pub fn add_time(&self, duration: Duration) {
125        self.total_time_us
126            .fetch_add(duration.as_micros() as u64, Ordering::Relaxed);
127    }
128
129    /// Get total request count
130    pub fn request_count(&self) -> u64 {
131        self.request_count.load(Ordering::Relaxed)
132    }
133
134    /// Get total error count
135    pub fn error_count(&self) -> u64 {
136        self.error_count.load(Ordering::Relaxed)
137    }
138
139    /// Get average processing time
140    pub fn average_time(&self) -> Duration {
141        let total_time = self.total_time_us.load(Ordering::Relaxed);
142        let count = self.request_count.load(Ordering::Relaxed);
143        total_time
144            .checked_div(count)
145            .map_or(Duration::ZERO, Duration::from_micros)
146    }
147}
148
149/// Middleware execution priority for ordering.
150#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
151pub enum MiddlewarePriority {
152    /// Highest priority - executed first in chain
153    Critical = 0,
154    /// High priority - authentication, security
155    High = 1,
156    /// Normal priority - business logic
157    #[default]
158    Normal = 2,
159    /// Low priority - logging, metrics
160    Low = 3,
161    /// Lowest priority - cleanup, finalization
162    Lowest = 4,
163}
164
165/// Enhanced middleware trait with context support and priority.
166#[async_trait]
167pub trait AdvancedMiddleware: Send + Sync {
168    /// Get middleware priority for execution ordering
169    fn priority(&self) -> MiddlewarePriority {
170        MiddlewarePriority::Normal
171    }
172
173    /// Get middleware name for identification
174    fn name(&self) -> &'static str {
175        "unknown"
176    }
177
178    /// Check if middleware should be executed for this context
179    async fn should_execute(&self, _context: &MiddlewareContext) -> bool {
180        true
181    }
182
183    /// Called before a request is sent with context.
184    async fn on_request_with_context(
185        &self,
186        request: &mut JSONRPCRequest,
187        context: &MiddlewareContext,
188    ) -> Result<()> {
189        let _ = (request, context);
190        Ok(())
191    }
192
193    /// Called after a response is received with context.
194    async fn on_response_with_context(
195        &self,
196        response: &mut JSONRPCResponse,
197        context: &MiddlewareContext,
198    ) -> Result<()> {
199        let _ = (response, context);
200        Ok(())
201    }
202
203    /// Called when a message is sent with context.
204    async fn on_send_with_context(
205        &self,
206        message: &TransportMessage,
207        context: &MiddlewareContext,
208    ) -> Result<()> {
209        let _ = (message, context);
210        Ok(())
211    }
212
213    /// Called when a message is received with context.
214    async fn on_receive_with_context(
215        &self,
216        message: &TransportMessage,
217        context: &MiddlewareContext,
218    ) -> Result<()> {
219        let _ = (message, context);
220        Ok(())
221    }
222
223    /// Called when an unsolicited notification is received with context.
224    ///
225    /// This enables middleware to process server-initiated notifications
226    /// (e.g., progress updates, resource changes) that arrive without
227    /// a corresponding request.
228    async fn on_notification_with_context(
229        &self,
230        notification: &mut JSONRPCNotification,
231        context: &MiddlewareContext,
232    ) -> Result<()> {
233        let _ = (notification, context);
234        Ok(())
235    }
236
237    /// Called when middleware chain starts
238    async fn on_chain_start(&self, _context: &MiddlewareContext) -> Result<()> {
239        Ok(())
240    }
241
242    /// Called when middleware chain completes
243    async fn on_chain_complete(&self, _context: &MiddlewareContext) -> Result<()> {
244        Ok(())
245    }
246
247    /// Called when an error occurs in the chain
248    async fn on_error(
249        &self,
250        _error: &crate::error::Error,
251        _context: &MiddlewareContext,
252    ) -> Result<()> {
253        Ok(())
254    }
255}
256
257/// Middleware that can intercept and modify requests and responses.
258///
259/// # Examples
260///
261/// ```rust
262/// use pmcp::shared::{Middleware, TransportMessage};
263/// use pmcp::types::{JSONRPCRequest, JSONRPCResponse, RequestId};
264/// use async_trait::async_trait;
265///
266/// // Custom middleware that adds timing information
267/// #[derive(Debug)]
268/// struct TimingMiddleware {
269///     start_time: std::time::Instant,
270/// }
271///
272/// impl TimingMiddleware {
273///     fn new() -> Self {
274///         Self { start_time: std::time::Instant::now() }
275///     }
276/// }
277///
278/// #[async_trait]
279/// impl Middleware for TimingMiddleware {
280///     async fn on_request(&self, request: &mut JSONRPCRequest) -> pmcp::Result<()> {
281///         // Add timing metadata to request params
282///         println!("Processing request {} at {}ms",
283///             request.method,
284///             self.start_time.elapsed().as_millis());
285///         Ok(())
286///     }
287///
288///     async fn on_response(&self, response: &mut JSONRPCResponse) -> pmcp::Result<()> {
289///         println!("Response for {:?} received at {}ms",
290///             response.id,
291///             self.start_time.elapsed().as_millis());
292///         Ok(())
293///     }
294/// }
295///
296/// # async fn example() -> pmcp::Result<()> {
297/// let middleware = TimingMiddleware::new();
298/// let mut request = JSONRPCRequest {
299///     jsonrpc: "2.0".to_string(),
300///     method: "test".to_string(),
301///     params: None,
302///     id: RequestId::from(123i64),
303/// };
304///
305/// // Process request through middleware
306/// middleware.on_request(&mut request).await?;
307/// # Ok(())
308/// # }
309/// ```
310#[async_trait]
311pub trait Middleware: Send + Sync {
312    /// Called before a request is sent.
313    async fn on_request(&self, request: &mut JSONRPCRequest) -> Result<()> {
314        let _ = request;
315        Ok(())
316    }
317
318    /// Called after a response is received.
319    async fn on_response(&self, response: &mut JSONRPCResponse) -> Result<()> {
320        let _ = response;
321        Ok(())
322    }
323
324    /// Called when a message is sent (any type).
325    async fn on_send(&self, message: &TransportMessage) -> Result<()> {
326        let _ = message;
327        Ok(())
328    }
329
330    /// Called when a message is received (any type).
331    async fn on_receive(&self, message: &TransportMessage) -> Result<()> {
332        let _ = message;
333        Ok(())
334    }
335
336    /// Called when an unsolicited notification is received.
337    ///
338    /// This enables middleware to process server-initiated notifications
339    /// (e.g., progress updates, resource changes) that arrive without
340    /// a corresponding request.
341    async fn on_notification(&self, notification: &mut JSONRPCNotification) -> Result<()> {
342        let _ = notification;
343        Ok(())
344    }
345}
346
347/// Enhanced middleware chain with priority ordering and context support.
348///
349/// # Examples
350///
351/// ```rust
352/// use pmcp::shared::{EnhancedMiddlewareChain, MiddlewareContext};
353/// use pmcp::types::{JSONRPCRequest, JSONRPCResponse, RequestId};
354/// use std::sync::Arc;
355///
356/// # async fn example() -> pmcp::Result<()> {
357/// // Create an enhanced middleware chain
358/// let mut chain = EnhancedMiddlewareChain::new();
359/// let context = MiddlewareContext::with_request_id("req-123".to_string());
360///
361/// // Create a request to process
362/// let mut request = JSONRPCRequest {
363///     jsonrpc: "2.0".to_string(),
364///     method: "prompts.get".to_string(),
365///     params: Some(serde_json::json!({
366///         "name": "code_review",
367///         "arguments": {"language": "rust", "style": "detailed"}
368///     })),
369///     id: RequestId::from(1001i64),
370/// };
371///
372/// // Process request through all middleware with context
373/// chain.process_request_with_context(&mut request, &context).await?;
374/// # Ok(())
375/// # }
376/// ```
377pub struct EnhancedMiddlewareChain {
378    middlewares: Vec<Arc<dyn AdvancedMiddleware>>,
379    auto_sort: bool,
380}
381
382impl fmt::Debug for EnhancedMiddlewareChain {
383    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
384        f.debug_struct("EnhancedMiddlewareChain")
385            .field("count", &self.middlewares.len())
386            .field("auto_sort", &self.auto_sort)
387            .finish()
388    }
389}
390
391impl Default for EnhancedMiddlewareChain {
392    fn default() -> Self {
393        Self::new()
394    }
395}
396
397impl EnhancedMiddlewareChain {
398    /// Create a new enhanced middleware chain with automatic sorting by priority.
399    pub fn new() -> Self {
400        Self {
401            middlewares: Vec::new(),
402            auto_sort: true,
403        }
404    }
405
406    /// Create a new chain without automatic sorting.
407    pub fn new_no_sort() -> Self {
408        Self {
409            middlewares: Vec::new(),
410            auto_sort: false,
411        }
412    }
413
414    /// Add an advanced middleware to the chain.
415    pub fn add(&mut self, middleware: Arc<dyn AdvancedMiddleware>) {
416        self.middlewares.push(middleware);
417        if self.auto_sort {
418            self.sort_by_priority();
419        }
420    }
421
422    /// Sort middleware by priority (critical first).
423    pub fn sort_by_priority(&mut self) {
424        self.middlewares.sort_by_key(|m| m.priority());
425    }
426
427    /// Get middleware count.
428    pub fn len(&self) -> usize {
429        self.middlewares.len()
430    }
431
432    /// Check if chain is empty.
433    pub fn is_empty(&self) -> bool {
434        self.middlewares.is_empty()
435    }
436
437    /// Process a request through all applicable middleware with context.
438    pub async fn process_request_with_context(
439        &self,
440        request: &mut JSONRPCRequest,
441        context: &MiddlewareContext,
442    ) -> Result<()> {
443        context.metrics.inc_requests();
444        let start_time = Instant::now();
445
446        // Notify chain start
447        for middleware in &self.middlewares {
448            if middleware.should_execute(context).await {
449                middleware.on_chain_start(context).await?;
450            }
451        }
452
453        // Process through middleware
454        for middleware in &self.middlewares {
455            if middleware.should_execute(context).await {
456                if let Err(e) = middleware.on_request_with_context(request, context).await {
457                    context.metrics.inc_errors();
458                    // Notify error to all middleware
459                    for m in &self.middlewares {
460                        if m.should_execute(context).await {
461                            let _ = m.on_error(&e, context).await;
462                        }
463                    }
464                    return Err(e);
465                }
466            }
467        }
468
469        // Notify chain complete
470        for middleware in &self.middlewares {
471            if middleware.should_execute(context).await {
472                middleware.on_chain_complete(context).await?;
473            }
474        }
475
476        context.metrics.add_time(start_time.elapsed());
477        Ok(())
478    }
479
480    /// Process a response through all applicable middleware with context.
481    pub async fn process_response_with_context(
482        &self,
483        response: &mut JSONRPCResponse,
484        context: &MiddlewareContext,
485    ) -> Result<()> {
486        let start_time = Instant::now();
487
488        // Process through middleware in reverse order for responses
489        for middleware in self.middlewares.iter().rev() {
490            if middleware.should_execute(context).await {
491                if let Err(e) = middleware.on_response_with_context(response, context).await {
492                    context.metrics.inc_errors();
493                    // Notify error to all middleware
494                    for m in &self.middlewares {
495                        if m.should_execute(context).await {
496                            let _ = m.on_error(&e, context).await;
497                        }
498                    }
499                    return Err(e);
500                }
501            }
502        }
503
504        context.metrics.add_time(start_time.elapsed());
505        Ok(())
506    }
507
508    /// Process an outgoing message through all applicable middleware.
509    pub async fn process_send_with_context(
510        &self,
511        message: &TransportMessage,
512        context: &MiddlewareContext,
513    ) -> Result<()> {
514        let start_time = Instant::now();
515
516        for middleware in &self.middlewares {
517            if middleware.should_execute(context).await {
518                if let Err(e) = middleware.on_send_with_context(message, context).await {
519                    context.metrics.inc_errors();
520                    for m in &self.middlewares {
521                        if m.should_execute(context).await {
522                            let _ = m.on_error(&e, context).await;
523                        }
524                    }
525                    return Err(e);
526                }
527            }
528        }
529
530        context.metrics.add_time(start_time.elapsed());
531        Ok(())
532    }
533
534    /// Process an incoming message through all applicable middleware.
535    pub async fn process_receive_with_context(
536        &self,
537        message: &TransportMessage,
538        context: &MiddlewareContext,
539    ) -> Result<()> {
540        let start_time = Instant::now();
541
542        for middleware in &self.middlewares {
543            if middleware.should_execute(context).await {
544                if let Err(e) = middleware.on_receive_with_context(message, context).await {
545                    context.metrics.inc_errors();
546                    for m in &self.middlewares {
547                        if m.should_execute(context).await {
548                            let _ = m.on_error(&e, context).await;
549                        }
550                    }
551                    return Err(e);
552                }
553            }
554        }
555
556        context.metrics.add_time(start_time.elapsed());
557        Ok(())
558    }
559
560    /// Process an unsolicited notification through all applicable middleware.
561    ///
562    /// This enables middleware to intercept and process server-initiated
563    /// notifications (e.g., progress updates, resource changes, SSE events)
564    /// that arrive without a corresponding request.
565    ///
566    /// # Examples
567    ///
568    /// ```rust
569    /// use pmcp::shared::{EnhancedMiddlewareChain, MiddlewareContext};
570    /// use pmcp::types::JSONRPCNotification;
571    ///
572    /// # async fn example() -> pmcp::Result<()> {
573    /// let chain = EnhancedMiddlewareChain::new();
574    /// let context = MiddlewareContext::default();
575    ///
576    /// let mut notification = JSONRPCNotification::new(
577    ///     "notifications/progress",
578    ///     Some(serde_json::json!({
579    ///         "progressToken": "token-123",
580    ///         "progress": 50,
581    ///         "total": 100
582    ///     }))
583    /// );
584    ///
585    /// // Process notification through middleware chain
586    /// chain.process_notification_with_context(&mut notification, &context).await?;
587    /// # Ok(())
588    /// # }
589    /// ```
590    pub async fn process_notification_with_context(
591        &self,
592        notification: &mut JSONRPCNotification,
593        context: &MiddlewareContext,
594    ) -> Result<()> {
595        let start_time = Instant::now();
596
597        // Process through middleware in order
598        for middleware in &self.middlewares {
599            if middleware.should_execute(context).await {
600                if let Err(e) = middleware
601                    .on_notification_with_context(notification, context)
602                    .await
603                {
604                    context.metrics.inc_errors();
605                    // Notify error to all middleware
606                    for m in &self.middlewares {
607                        if m.should_execute(context).await {
608                            let _ = m.on_error(&e, context).await;
609                        }
610                    }
611                    return Err(e);
612                }
613            }
614        }
615
616        context.metrics.add_time(start_time.elapsed());
617        Ok(())
618    }
619
620    /// Get performance metrics for the chain.
621    pub fn get_metrics(&self) -> Vec<Arc<PerformanceMetrics>> {
622        // This would collect metrics from all contexts that have been processed
623        // For now, we return an empty vector as metrics are stored per-context
624        Vec::new()
625    }
626}
627
628/// Chain of middleware handlers (legacy).
629///
630/// # Examples
631///
632/// ```rust
633/// use pmcp::shared::{MiddlewareChain, LoggingMiddleware, AuthMiddleware, RetryMiddleware};
634/// use pmcp::types::{JSONRPCRequest, JSONRPCResponse, RequestId};
635/// use std::sync::Arc;
636/// use tracing::Level;
637///
638/// # async fn example() -> pmcp::Result<()> {
639/// // Create a middleware chain
640/// let mut chain = MiddlewareChain::new();
641///
642/// // Add different types of middleware in order
643/// chain.add(Arc::new(LoggingMiddleware::new(Level::INFO)));
644/// chain.add(Arc::new(AuthMiddleware::new("Bearer token-123".to_string())));
645/// chain.add(Arc::new(RetryMiddleware::default()));
646///
647/// // Create a request to process
648/// let mut request = JSONRPCRequest {
649///     jsonrpc: "2.0".to_string(),
650///     method: "prompts.get".to_string(),
651///     params: Some(serde_json::json!({
652///         "name": "code_review",
653///         "arguments": {"language": "rust", "style": "detailed"}
654///     })),
655///     id: RequestId::from(1001i64),
656/// };
657///
658/// // Process request through all middleware in order
659/// chain.process_request(&mut request).await?;
660///
661/// // Create a response to process
662/// let mut response = JSONRPCResponse {
663///     jsonrpc: "2.0".to_string(),
664///     id: RequestId::from(1001i64),
665///     payload: pmcp::types::jsonrpc::ResponsePayload::Result(
666///         serde_json::json!({"prompt": "Review the following code..."})
667///     ),
668/// };
669///
670/// // Process response through all middleware
671/// chain.process_response(&mut response).await?;
672///
673/// // The chain processes middleware in the order they were added
674/// // 1. LoggingMiddleware logs the request/response
675/// // 2. AuthMiddleware adds authentication
676/// // 3. RetryMiddleware configures retry behavior
677/// # Ok(())
678/// # }
679/// ```
680pub struct MiddlewareChain {
681    middlewares: Vec<Arc<dyn Middleware>>,
682}
683
684impl fmt::Debug for MiddlewareChain {
685    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
686        f.debug_struct("MiddlewareChain")
687            .field("count", &self.middlewares.len())
688            .finish()
689    }
690}
691
692impl Default for MiddlewareChain {
693    fn default() -> Self {
694        Self::new()
695    }
696}
697
698impl MiddlewareChain {
699    /// Create a new empty middleware chain.
700    pub fn new() -> Self {
701        Self {
702            middlewares: Vec::new(),
703        }
704    }
705
706    /// Add a middleware to the chain.
707    pub fn add(&mut self, middleware: Arc<dyn Middleware>) {
708        self.middlewares.push(middleware);
709    }
710
711    /// Process a request through all middleware.
712    pub async fn process_request(&self, request: &mut JSONRPCRequest) -> Result<()> {
713        for middleware in &self.middlewares {
714            middleware.on_request(request).await?;
715        }
716        Ok(())
717    }
718
719    /// Process a response through all middleware.
720    pub async fn process_response(&self, response: &mut JSONRPCResponse) -> Result<()> {
721        for middleware in &self.middlewares {
722            middleware.on_response(response).await?;
723        }
724        Ok(())
725    }
726
727    /// Process an outgoing message through all middleware.
728    pub async fn process_send(&self, message: &TransportMessage) -> Result<()> {
729        for middleware in &self.middlewares {
730            middleware.on_send(message).await?;
731        }
732        Ok(())
733    }
734
735    /// Process an incoming message through all middleware.
736    pub async fn process_receive(&self, message: &TransportMessage) -> Result<()> {
737        for middleware in &self.middlewares {
738            middleware.on_receive(message).await?;
739        }
740        Ok(())
741    }
742
743    /// Process an unsolicited notification through all middleware.
744    ///
745    /// This enables middleware to intercept and process server-initiated
746    /// notifications (e.g., progress updates, resource changes) that arrive
747    /// without a corresponding request.
748    pub async fn process_notification(&self, notification: &mut JSONRPCNotification) -> Result<()> {
749        for middleware in &self.middlewares {
750            middleware.on_notification(notification).await?;
751        }
752        Ok(())
753    }
754}
755
756/// Logging middleware that logs all messages.
757///
758/// # Examples
759///
760/// ```rust
761/// use pmcp::shared::{LoggingMiddleware, Middleware};
762/// use pmcp::types::{JSONRPCRequest, RequestId};
763/// use tracing::Level;
764///
765/// # async fn example() -> pmcp::Result<()> {
766/// // Create logging middleware with different levels
767/// let debug_logger = LoggingMiddleware::new(Level::DEBUG);
768/// let info_logger = LoggingMiddleware::new(Level::INFO);
769/// let default_logger = LoggingMiddleware::default(); // Uses DEBUG level
770///
771/// let mut request = JSONRPCRequest {
772///     jsonrpc: "2.0".to_string(),
773///     method: "tools.list".to_string(),
774///     params: Some(serde_json::json!({"category": "development"})),
775///     id: RequestId::from(456i64),
776/// };
777///
778/// // Log at different levels
779/// debug_logger.on_request(&mut request).await?;
780/// info_logger.on_request(&mut request).await?;
781/// default_logger.on_request(&mut request).await?;
782/// # Ok(())
783/// # }
784/// ```
785#[derive(Debug)]
786pub struct LoggingMiddleware {
787    level: tracing::Level,
788}
789
790impl LoggingMiddleware {
791    /// Create a new logging middleware with the specified level.
792    pub fn new(level: tracing::Level) -> Self {
793        Self { level }
794    }
795}
796
797impl Default for LoggingMiddleware {
798    fn default() -> Self {
799        Self::new(tracing::Level::DEBUG)
800    }
801}
802
803#[async_trait]
804impl Middleware for LoggingMiddleware {
805    async fn on_request(&self, request: &mut JSONRPCRequest) -> Result<()> {
806        match self.level {
807            tracing::Level::TRACE => tracing::trace!("Sending request: {:?}", request),
808            tracing::Level::DEBUG => tracing::debug!("Sending request: {}", request.method),
809            tracing::Level::INFO => tracing::info!("Sending request: {}", request.method),
810            tracing::Level::WARN => tracing::warn!("Sending request: {}", request.method),
811            tracing::Level::ERROR => tracing::error!("Sending request: {}", request.method),
812        }
813        Ok(())
814    }
815
816    async fn on_response(&self, response: &mut JSONRPCResponse) -> Result<()> {
817        match self.level {
818            tracing::Level::TRACE => tracing::trace!("Received response: {:?}", response),
819            tracing::Level::DEBUG => tracing::debug!("Received response for: {:?}", response.id),
820            tracing::Level::INFO => tracing::info!("Received response"),
821            tracing::Level::WARN => tracing::warn!("Received response"),
822            tracing::Level::ERROR => tracing::error!("Received response"),
823        }
824        Ok(())
825    }
826}
827
828/// Authentication middleware that adds auth headers.
829///
830/// # Examples
831///
832/// ```rust
833/// use pmcp::shared::{AuthMiddleware, Middleware};
834/// use pmcp::types::{JSONRPCRequest, RequestId};
835///
836/// # async fn example() -> pmcp::Result<()> {
837/// // Create auth middleware with API token
838/// let auth_middleware = AuthMiddleware::new("Bearer api-token-12345".to_string());
839///
840/// let mut request = JSONRPCRequest {
841///     jsonrpc: "2.0".to_string(),
842///     method: "resources.read".to_string(),
843///     params: Some(serde_json::json!({"uri": "file:///secure/data.txt"})),
844///     id: RequestId::from(789i64),
845/// };
846///
847/// // Process request and add authentication
848/// auth_middleware.on_request(&mut request).await?;
849///
850/// // In a real implementation, the middleware would modify the request
851/// // to include authentication information
852/// # Ok(())
853/// # }
854/// ```
855#[derive(Debug)]
856pub struct AuthMiddleware {
857    #[allow(dead_code)]
858    auth_token: String,
859}
860
861impl AuthMiddleware {
862    /// Create a new auth middleware with the given token.
863    pub fn new(auth_token: String) -> Self {
864        Self { auth_token }
865    }
866}
867
868#[async_trait]
869impl Middleware for AuthMiddleware {
870    async fn on_request(&self, request: &mut JSONRPCRequest) -> Result<()> {
871        // In a real implementation, this would add auth headers
872        // For JSON-RPC, we might add auth to params or use a wrapper
873        tracing::debug!("Adding authentication to request: {}", request.method);
874        Ok(())
875    }
876}
877
878/// Retry middleware that implements exponential backoff.
879///
880/// # Examples
881///
882/// ```rust
883/// use pmcp::shared::{RetryMiddleware, Middleware};
884/// use pmcp::types::{JSONRPCRequest, RequestId};
885///
886/// # async fn example() -> pmcp::Result<()> {
887/// // Create retry middleware with custom settings
888/// let retry_middleware = RetryMiddleware::new(
889///     5,      // max_retries
890///     1000,   // initial_delay_ms (1 second)
891///     30000   // max_delay_ms (30 seconds)
892/// );
893///
894/// // Default retry middleware (3 retries, 1s initial, 30s max)
895/// let default_retry = RetryMiddleware::default();
896///
897/// let mut request = JSONRPCRequest {
898///     jsonrpc: "2.0".to_string(),
899///     method: "tools.call".to_string(),
900///     params: Some(serde_json::json!({
901///         "name": "network_tool",
902///         "arguments": {"url": "https://api.example.com/data"}
903///     })),
904///     id: RequestId::from(999i64),
905/// };
906///
907/// // Configure request for retry handling
908/// retry_middleware.on_request(&mut request).await?;
909/// default_retry.on_request(&mut request).await?;
910///
911/// // The actual retry logic would be implemented at the transport level
912/// # Ok(())
913/// # }
914/// ```
915#[derive(Debug)]
916pub struct RetryMiddleware {
917    max_retries: u32,
918    #[allow(dead_code)]
919    initial_delay_ms: u64,
920    #[allow(dead_code)]
921    max_delay_ms: u64,
922}
923
924impl RetryMiddleware {
925    /// Create a new retry middleware.
926    pub fn new(max_retries: u32, initial_delay_ms: u64, max_delay_ms: u64) -> Self {
927        Self {
928            max_retries,
929            initial_delay_ms,
930            max_delay_ms,
931        }
932    }
933}
934
935impl Default for RetryMiddleware {
936    fn default() -> Self {
937        Self::new(3, 1000, 30000)
938    }
939}
940
941#[async_trait]
942impl Middleware for RetryMiddleware {
943    async fn on_request(&self, request: &mut JSONRPCRequest) -> Result<()> {
944        // Retry logic would be implemented at the transport level
945        // This middleware just adds metadata for retry handling
946        tracing::debug!(
947            "Request {} configured with max {} retries",
948            request.method,
949            self.max_retries
950        );
951        Ok(())
952    }
953}
954
955/// Rate limiting middleware with token bucket algorithm.
956///
957/// # Examples
958///
959/// ```rust
960/// use pmcp::shared::{RateLimitMiddleware, AdvancedMiddleware, MiddlewareContext};
961/// use pmcp::types::{JSONRPCRequest, RequestId};
962/// use std::time::Duration;
963///
964/// # async fn example() -> pmcp::Result<()> {
965/// // Create rate limiter: 10 requests per second, burst of 20
966/// let rate_limiter = RateLimitMiddleware::new(10, 20, Duration::from_secs(1));
967/// let context = MiddlewareContext::default();
968///
969/// let mut request = JSONRPCRequest {
970///     jsonrpc: "2.0".to_string(),
971///     method: "tools.call".to_string(),
972///     params: Some(serde_json::json!({"name": "api_call"})),
973///     id: RequestId::from(123i64),
974/// };
975///
976/// // This will succeed if under rate limit, fail if over
977/// rate_limiter.on_request_with_context(&mut request, &context).await?;
978/// # Ok(())
979/// # }
980/// ```
981#[derive(Debug)]
982pub struct RateLimitMiddleware {
983    max_requests: u32,
984    bucket_size: u32,
985    refill_duration: Duration,
986    tokens: Arc<AtomicUsize>,
987    last_refill: Arc<RwLock<Instant>>,
988}
989
990impl RateLimitMiddleware {
991    /// Create a new rate limiting middleware.
992    pub fn new(max_requests: u32, bucket_size: u32, refill_duration: Duration) -> Self {
993        Self {
994            max_requests,
995            bucket_size,
996            refill_duration,
997            tokens: Arc::new(AtomicUsize::new(bucket_size as usize)),
998            last_refill: Arc::new(RwLock::new(Instant::now())),
999        }
1000    }
1001
1002    /// Check if request is within rate limits.
1003    fn check_rate_limit(&self) -> bool {
1004        // Refill tokens based on time elapsed
1005        let now = Instant::now();
1006        let mut last_refill = self.last_refill.write();
1007        let elapsed = now.duration_since(*last_refill);
1008
1009        if elapsed >= self.refill_duration {
1010            let refill_count = (elapsed.as_millis() / self.refill_duration.as_millis()) as u32;
1011            let tokens_to_add = (refill_count * self.max_requests).min(self.bucket_size);
1012
1013            self.tokens.store(
1014                (self.tokens.load(Ordering::Relaxed) + tokens_to_add as usize)
1015                    .min(self.bucket_size as usize),
1016                Ordering::Relaxed,
1017            );
1018            *last_refill = now;
1019        }
1020
1021        // Try to consume a token
1022        loop {
1023            let current = self.tokens.load(Ordering::Relaxed);
1024            if current == 0 {
1025                return false;
1026            }
1027            if self
1028                .tokens
1029                .compare_exchange_weak(current, current - 1, Ordering::Relaxed, Ordering::Relaxed)
1030                .is_ok()
1031            {
1032                return true;
1033            }
1034        }
1035    }
1036}
1037
1038#[async_trait]
1039impl AdvancedMiddleware for RateLimitMiddleware {
1040    fn name(&self) -> &'static str {
1041        "rate_limit"
1042    }
1043
1044    fn priority(&self) -> MiddlewarePriority {
1045        MiddlewarePriority::High
1046    }
1047
1048    async fn on_request_with_context(
1049        &self,
1050        request: &mut JSONRPCRequest,
1051        context: &MiddlewareContext,
1052    ) -> Result<()> {
1053        if !self.check_rate_limit() {
1054            tracing::warn!("Rate limit exceeded for request: {}", request.method);
1055            context.record_metric("rate_limit_exceeded".to_string(), 1.0);
1056            return Err(crate::error::Error::RateLimited);
1057        }
1058
1059        tracing::debug!("Rate limit check passed for request: {}", request.method);
1060        context.record_metric("rate_limit_passed".to_string(), 1.0);
1061        Ok(())
1062    }
1063}
1064
1065/// Circuit breaker middleware for fault tolerance.
1066///
1067/// # Examples
1068///
1069/// ```rust
1070/// use pmcp::shared::{CircuitBreakerMiddleware, AdvancedMiddleware, MiddlewareContext};
1071/// use pmcp::types::{JSONRPCRequest, RequestId};
1072/// use std::time::Duration;
1073///
1074/// # async fn example() -> pmcp::Result<()> {
1075/// // Circuit breaker: 5 failures in 60s window trips for 30s
1076/// let circuit_breaker = CircuitBreakerMiddleware::new(
1077///     5,                          // failure_threshold
1078///     Duration::from_mins(1),    // time_window
1079///     Duration::from_secs(30),    // timeout_duration
1080/// );
1081/// let context = MiddlewareContext::default();
1082///
1083/// let mut request = JSONRPCRequest {
1084///     jsonrpc: "2.0".to_string(),
1085///     method: "external_service.call".to_string(),
1086///     params: Some(serde_json::json!({"data": "test"})),
1087///     id: RequestId::from(456i64),
1088/// };
1089///
1090/// // This will fail fast if circuit is open
1091/// circuit_breaker.on_request_with_context(&mut request, &context).await?;
1092/// # Ok(())
1093/// # }
1094/// ```
1095#[derive(Debug)]
1096pub struct CircuitBreakerMiddleware {
1097    failure_threshold: u32,
1098    time_window: Duration,
1099    timeout_duration: Duration,
1100    failure_count: Arc<AtomicU64>,
1101    last_failure: Arc<RwLock<Option<Instant>>>,
1102    circuit_open_time: Arc<RwLock<Option<Instant>>>,
1103}
1104
1105impl CircuitBreakerMiddleware {
1106    /// Create a new circuit breaker middleware.
1107    pub fn new(failure_threshold: u32, time_window: Duration, timeout_duration: Duration) -> Self {
1108        Self {
1109            failure_threshold,
1110            time_window,
1111            timeout_duration,
1112            failure_count: Arc::new(AtomicU64::new(0)),
1113            last_failure: Arc::new(RwLock::new(None)),
1114            circuit_open_time: Arc::new(RwLock::new(None)),
1115        }
1116    }
1117
1118    /// Check if circuit breaker should allow the request.
1119    fn should_allow_request(&self) -> bool {
1120        let now = Instant::now();
1121
1122        // Check if circuit is open and should transition to half-open
1123        let open_time_value = *self.circuit_open_time.read();
1124        if let Some(open_time) = open_time_value {
1125            if now.duration_since(open_time) > self.timeout_duration {
1126                // Transition to half-open: allow one request through
1127                *self.circuit_open_time.write() = None;
1128                self.failure_count.store(0, Ordering::Relaxed);
1129                return true;
1130            }
1131            return false; // Circuit is still open
1132        }
1133
1134        // Reset failure count if outside time window
1135        let last_failure_value = *self.last_failure.read();
1136        if let Some(last_failure) = last_failure_value {
1137            if now.duration_since(last_failure) > self.time_window {
1138                self.failure_count.store(0, Ordering::Relaxed);
1139            }
1140        }
1141
1142        // Check if failure threshold exceeded
1143        self.failure_count.load(Ordering::Relaxed) < self.failure_threshold as u64
1144    }
1145
1146    /// Record a failure and possibly open the circuit.
1147    fn record_failure(&self) {
1148        let now = Instant::now();
1149        let failures = self.failure_count.fetch_add(1, Ordering::Relaxed) + 1;
1150        *self.last_failure.write() = Some(now);
1151
1152        if failures >= self.failure_threshold as u64 {
1153            *self.circuit_open_time.write() = Some(now);
1154            tracing::warn!("Circuit breaker opened due to {} failures", failures);
1155        }
1156    }
1157}
1158
1159#[async_trait]
1160impl AdvancedMiddleware for CircuitBreakerMiddleware {
1161    fn name(&self) -> &'static str {
1162        "circuit_breaker"
1163    }
1164
1165    fn priority(&self) -> MiddlewarePriority {
1166        MiddlewarePriority::High
1167    }
1168
1169    async fn on_request_with_context(
1170        &self,
1171        request: &mut JSONRPCRequest,
1172        context: &MiddlewareContext,
1173    ) -> Result<()> {
1174        if !self.should_allow_request() {
1175            tracing::warn!(
1176                "Circuit breaker open, rejecting request: {}",
1177                request.method
1178            );
1179            context.record_metric("circuit_breaker_open".to_string(), 1.0);
1180            return Err(crate::error::Error::CircuitBreakerOpen);
1181        }
1182
1183        context.record_metric("circuit_breaker_allowed".to_string(), 1.0);
1184        Ok(())
1185    }
1186
1187    async fn on_error(
1188        &self,
1189        _error: &crate::error::Error,
1190        _context: &MiddlewareContext,
1191    ) -> Result<()> {
1192        self.record_failure();
1193        Ok(())
1194    }
1195}
1196
1197/// Metrics collection middleware for observability.
1198///
1199/// # Examples
1200///
1201/// ```rust
1202/// use pmcp::shared::{MetricsMiddleware, AdvancedMiddleware, MiddlewareContext};
1203/// use pmcp::types::{JSONRPCRequest, RequestId};
1204///
1205/// # async fn example() -> pmcp::Result<()> {
1206/// let metrics = MetricsMiddleware::new("pmcp_client".to_string());
1207/// let context = MiddlewareContext::default();
1208///
1209/// let mut request = JSONRPCRequest {
1210///     jsonrpc: "2.0".to_string(),
1211///     method: "resources.list".to_string(),
1212///     params: None,
1213///     id: RequestId::from(789i64),
1214/// };
1215///
1216/// // Automatically collects timing and count metrics
1217/// metrics.on_request_with_context(&mut request, &context).await?;
1218/// # Ok(())
1219/// # }
1220/// ```
1221#[derive(Debug)]
1222pub struct MetricsMiddleware {
1223    service_name: String,
1224    request_counts: Arc<DashMap<String, AtomicU64>>,
1225    request_durations: Arc<DashMap<String, AtomicU64>>,
1226    error_counts: Arc<DashMap<String, AtomicU64>>,
1227}
1228
1229impl MetricsMiddleware {
1230    /// Create a new metrics collection middleware.
1231    pub fn new(service_name: String) -> Self {
1232        Self {
1233            service_name,
1234            request_counts: Arc::new(DashMap::new()),
1235            request_durations: Arc::new(DashMap::new()),
1236            error_counts: Arc::new(DashMap::new()),
1237        }
1238    }
1239
1240    /// Get request count for a method.
1241    pub fn get_request_count(&self, method: &str) -> u64 {
1242        self.request_counts
1243            .get(method)
1244            .map_or(0, |c| c.load(Ordering::Relaxed))
1245    }
1246
1247    /// Get error count for a method.
1248    pub fn get_error_count(&self, method: &str) -> u64 {
1249        self.error_counts
1250            .get(method)
1251            .map_or(0, |c| c.load(Ordering::Relaxed))
1252    }
1253
1254    /// Get average duration for a method in microseconds.
1255    pub fn get_average_duration(&self, method: &str) -> u64 {
1256        let total_duration = self
1257            .request_durations
1258            .get(method)
1259            .map_or(0, |d| d.load(Ordering::Relaxed));
1260        let count = self.get_request_count(method);
1261        total_duration.checked_div(count).unwrap_or(0)
1262    }
1263}
1264
1265#[async_trait]
1266impl AdvancedMiddleware for MetricsMiddleware {
1267    fn name(&self) -> &'static str {
1268        "metrics"
1269    }
1270
1271    fn priority(&self) -> MiddlewarePriority {
1272        MiddlewarePriority::Low
1273    }
1274
1275    async fn on_request_with_context(
1276        &self,
1277        request: &mut JSONRPCRequest,
1278        context: &MiddlewareContext,
1279    ) -> Result<()> {
1280        // Increment request count
1281        self.request_counts
1282            .entry(request.method.clone())
1283            .or_insert_with(|| AtomicU64::new(0))
1284            .fetch_add(1, Ordering::Relaxed);
1285
1286        context.set_metadata(
1287            "request_start_time".to_string(),
1288            context.start_time.elapsed().as_micros().to_string(),
1289        );
1290        context.set_metadata("service_name".to_string(), self.service_name.clone());
1291
1292        tracing::debug!(
1293            "Metrics recorded for request: {} (service: {})",
1294            request.method,
1295            self.service_name
1296        );
1297        Ok(())
1298    }
1299
1300    async fn on_response_with_context(
1301        &self,
1302        response: &mut JSONRPCResponse,
1303        context: &MiddlewareContext,
1304    ) -> Result<()> {
1305        // Record response time if we have a request method in context
1306        let duration_us = context.elapsed().as_micros() as u64;
1307
1308        if let Some(method) = context.get_metadata("method") {
1309            self.request_durations
1310                .entry(method)
1311                .or_insert_with(|| AtomicU64::new(0))
1312                .fetch_add(duration_us, Ordering::Relaxed);
1313        }
1314
1315        tracing::debug!(
1316            "Response metrics recorded for ID: {:?} ({}μs)",
1317            response.id,
1318            duration_us
1319        );
1320        Ok(())
1321    }
1322
1323    async fn on_error(
1324        &self,
1325        error: &crate::error::Error,
1326        context: &MiddlewareContext,
1327    ) -> Result<()> {
1328        if let Some(method) = context.get_metadata("method") {
1329            self.error_counts
1330                .entry(method)
1331                .or_insert_with(|| AtomicU64::new(0))
1332                .fetch_add(1, Ordering::Relaxed);
1333        }
1334
1335        tracing::warn!("Error recorded in metrics: {:?}", error);
1336        Ok(())
1337    }
1338}
1339
1340/// Compression middleware for reducing message size.
1341///
1342/// # Examples
1343///
1344/// ```rust
1345/// use pmcp::shared::{CompressionMiddleware, AdvancedMiddleware, MiddlewareContext, CompressionType};
1346/// use pmcp::types::{JSONRPCRequest, RequestId};
1347///
1348/// # async fn example() -> pmcp::Result<()> {
1349/// let compression = CompressionMiddleware::new(CompressionType::Gzip, 1024);
1350/// let context = MiddlewareContext::default();
1351///
1352/// let mut request = JSONRPCRequest {
1353///     jsonrpc: "2.0".to_string(),
1354///     method: "resources.read".to_string(),
1355///     params: Some(serde_json::json!({"uri": "file:///large_file.json"})),
1356///     id: RequestId::from(101i64),
1357/// };
1358///
1359/// // Compresses request if over threshold
1360/// compression.on_request_with_context(&mut request, &context).await?;
1361/// # Ok(())
1362/// # }
1363/// ```
1364#[derive(Debug, Clone, Copy)]
1365pub enum CompressionType {
1366    /// No compression
1367    None,
1368    /// Gzip compression
1369    Gzip,
1370    /// Deflate compression
1371    Deflate,
1372}
1373
1374/// Compression middleware for reducing message size.
1375#[derive(Debug)]
1376pub struct CompressionMiddleware {
1377    compression_type: CompressionType,
1378    min_size: usize,
1379}
1380
1381impl CompressionMiddleware {
1382    /// Create a new compression middleware.
1383    pub fn new(compression_type: CompressionType, min_size: usize) -> Self {
1384        Self {
1385            compression_type,
1386            min_size,
1387        }
1388    }
1389
1390    /// Check if content should be compressed.
1391    fn should_compress(&self, content_size: usize) -> bool {
1392        content_size >= self.min_size && !matches!(self.compression_type, CompressionType::None)
1393    }
1394}
1395
1396#[async_trait]
1397impl AdvancedMiddleware for CompressionMiddleware {
1398    fn name(&self) -> &'static str {
1399        "compression"
1400    }
1401
1402    fn priority(&self) -> MiddlewarePriority {
1403        MiddlewarePriority::Normal
1404    }
1405
1406    async fn on_send_with_context(
1407        &self,
1408        message: &TransportMessage,
1409        context: &MiddlewareContext,
1410    ) -> Result<()> {
1411        let serialized = serde_json::to_string(message).unwrap_or_default();
1412        let content_size = serialized.len();
1413
1414        if self.should_compress(content_size) {
1415            context.set_metadata(
1416                "compression_type".to_string(),
1417                format!("{:?}", self.compression_type),
1418            );
1419            context.record_metric("compression_original_size".to_string(), content_size as f64);
1420
1421            tracing::debug!("Compression applied to message of {} bytes", content_size);
1422            // In a real implementation, this would compress the message content
1423        }
1424
1425        Ok(())
1426    }
1427}
1428
1429#[cfg(test)]
1430mod tests {
1431    use super::*;
1432    use crate::types::RequestId;
1433
1434    #[tokio::test]
1435    async fn test_middleware_chain() {
1436        let mut chain = MiddlewareChain::new();
1437        chain.add(Arc::new(LoggingMiddleware::default()));
1438
1439        let mut request = JSONRPCRequest {
1440            jsonrpc: "2.0".to_string(),
1441            id: RequestId::from(1i64),
1442            method: "test".to_string(),
1443            params: None,
1444        };
1445
1446        assert!(chain.process_request(&mut request).await.is_ok());
1447    }
1448
1449    #[tokio::test]
1450    async fn test_auth_middleware() {
1451        let middleware = AuthMiddleware::new("test-token".to_string());
1452
1453        let mut request = JSONRPCRequest {
1454            jsonrpc: "2.0".to_string(),
1455            id: RequestId::from(1i64),
1456            method: "test".to_string(),
1457            params: None,
1458        };
1459
1460        assert!(middleware.on_request(&mut request).await.is_ok());
1461    }
1462
1463    #[tokio::test]
1464    async fn test_notification_middleware_legacy() {
1465        let mut chain = MiddlewareChain::new();
1466        chain.add(Arc::new(LoggingMiddleware::default()));
1467
1468        let mut notification = JSONRPCNotification::new(
1469            "notifications/progress",
1470            Some(serde_json::json!({
1471                "progressToken": "test-123",
1472                "progress": 50,
1473                "total": 100
1474            })),
1475        );
1476
1477        // Should process without error
1478        assert!(chain.process_notification(&mut notification).await.is_ok());
1479    }
1480
1481    #[tokio::test]
1482    async fn test_notification_middleware_enhanced() {
1483        let mut chain = EnhancedMiddlewareChain::new();
1484        chain.add(Arc::new(MetricsMiddleware::new("test-service".to_string())));
1485
1486        let context = MiddlewareContext::with_request_id("notif-001".to_string());
1487
1488        let mut notification = JSONRPCNotification::new(
1489            "notifications/resourceUpdated",
1490            Some(serde_json::json!({
1491                "uri": "file:///test.txt",
1492                "type": "modified"
1493            })),
1494        );
1495
1496        // Should process notification through enhanced middleware
1497        assert!(chain
1498            .process_notification_with_context(&mut notification, &context)
1499            .await
1500            .is_ok());
1501
1502        // Verify metrics were not incremented for notifications (they're not requests)
1503        let stats = context.metrics;
1504        assert_eq!(stats.request_count(), 0);
1505    }
1506
1507    /// Test middleware that appends metadata to notifications
1508    struct NotificationMetadataMiddleware {
1509        tag: String,
1510    }
1511
1512    #[async_trait::async_trait]
1513    impl AdvancedMiddleware for NotificationMetadataMiddleware {
1514        fn name(&self) -> &'static str {
1515            "notification_metadata"
1516        }
1517
1518        async fn on_notification_with_context(
1519            &self,
1520            notification: &mut JSONRPCNotification,
1521            context: &MiddlewareContext,
1522        ) -> Result<()> {
1523            // Store notification method in context metadata
1524            context.set_metadata(
1525                "notification_method".to_string(),
1526                notification.method.clone(),
1527            );
1528            context.set_metadata("middleware_tag".to_string(), self.tag.clone());
1529            Ok(())
1530        }
1531    }
1532
1533    #[tokio::test]
1534    async fn test_notification_metadata_middleware() {
1535        let mut chain = EnhancedMiddlewareChain::new();
1536        chain.add(Arc::new(NotificationMetadataMiddleware {
1537            tag: "test-tag".to_string(),
1538        }));
1539
1540        let context = MiddlewareContext::with_request_id("notif-002".to_string());
1541
1542        let mut notification = JSONRPCNotification::new(
1543            "notifications/cancelled",
1544            Some(serde_json::json!({
1545                "requestId": "req-123",
1546                "reason": "user cancelled"
1547            })),
1548        );
1549
1550        chain
1551            .process_notification_with_context(&mut notification, &context)
1552            .await
1553            .unwrap();
1554
1555        // Verify metadata was set by middleware
1556        assert_eq!(
1557            context.get_metadata("notification_method"),
1558            Some("notifications/cancelled".to_string())
1559        );
1560        assert_eq!(
1561            context.get_metadata("middleware_tag"),
1562            Some("test-tag".to_string())
1563        );
1564    }
1565
1566    #[tokio::test]
1567    async fn test_notification_error_handling() {
1568        /// Test middleware that fails on specific notification
1569        struct FailingNotificationMiddleware;
1570
1571        #[async_trait::async_trait]
1572        impl AdvancedMiddleware for FailingNotificationMiddleware {
1573            fn name(&self) -> &'static str {
1574                "failing_notification"
1575            }
1576
1577            async fn on_notification_with_context(
1578                &self,
1579                notification: &mut JSONRPCNotification,
1580                _context: &MiddlewareContext,
1581            ) -> Result<()> {
1582                if notification.method == "notifications/error" {
1583                    return Err(crate::Error::internal("notification processing failed"));
1584                }
1585                Ok(())
1586            }
1587        }
1588
1589        let mut chain = EnhancedMiddlewareChain::new();
1590        chain.add(Arc::new(FailingNotificationMiddleware));
1591
1592        let context = MiddlewareContext::default();
1593
1594        // Success case
1595        let mut ok_notification =
1596            JSONRPCNotification::new("notifications/ok", None::<serde_json::Value>);
1597        assert!(chain
1598            .process_notification_with_context(&mut ok_notification, &context)
1599            .await
1600            .is_ok());
1601
1602        // Error case
1603        let mut error_notification =
1604            JSONRPCNotification::new("notifications/error", None::<serde_json::Value>);
1605        let result = chain
1606            .process_notification_with_context(&mut error_notification, &context)
1607            .await;
1608        assert!(result.is_err());
1609
1610        // Verify error was counted
1611        assert_eq!(context.metrics.error_count(), 1);
1612    }
1613}