1use mocopr_core::prelude::*;
4use tracing::{error, info, warn};
5
6#[async_trait::async_trait]
8pub trait Middleware: Send + Sync {
9 async fn before_request(&self, request: &JsonRpcRequest) -> Result<()>;
11
12 async fn after_response(
14 &self,
15 request: &JsonRpcRequest,
16 response: &JsonRpcResponse,
17 ) -> Result<()>;
18
19 async fn on_error(&self, request: &JsonRpcRequest, error: &Error) -> Result<()>;
21}
22
23pub struct LoggingMiddleware {
25 pub log_requests: bool,
26 pub log_responses: bool,
27 pub log_timing: bool,
28}
29
30impl LoggingMiddleware {
31 pub fn new() -> Self {
32 Self {
33 log_requests: true,
34 log_responses: false,
35 log_timing: true,
36 }
37 }
38
39 pub fn with_requests(mut self, enabled: bool) -> Self {
40 self.log_requests = enabled;
41 self
42 }
43
44 pub fn with_responses(mut self, enabled: bool) -> Self {
45 self.log_responses = enabled;
46 self
47 }
48
49 pub fn with_timing(mut self, enabled: bool) -> Self {
50 self.log_timing = enabled;
51 self
52 }
53}
54
55impl Default for LoggingMiddleware {
56 fn default() -> Self {
57 Self::new()
58 }
59}
60
61#[async_trait::async_trait]
62impl Middleware for LoggingMiddleware {
63 async fn before_request(&self, request: &JsonRpcRequest) -> Result<()> {
64 if self.log_requests {
65 info!("Request: {} (ID: {:?})", request.method, request.id);
66 }
67 Ok(())
68 }
69
70 async fn after_response(
71 &self,
72 request: &JsonRpcRequest,
73 response: &JsonRpcResponse,
74 ) -> Result<()> {
75 if self.log_responses {
76 if response.error.is_some() {
77 warn!(
78 "Response error for {}: {:?}",
79 request.method, response.error
80 );
81 } else {
82 info!(
83 "Response success for {} (ID: {:?})",
84 request.method, request.id
85 );
86 }
87 }
88 Ok(())
89 }
90
91 async fn on_error(&self, request: &JsonRpcRequest, error: &Error) -> Result<()> {
92 error!("Error processing {}: {}", request.method, error);
93 Ok(())
94 }
95}
96
97pub struct RateLimitMiddleware {
99 rate_limiter: std::sync::Arc<tokio::sync::Mutex<mocopr_core::utils::RateLimiter>>,
100}
101
102impl RateLimitMiddleware {
103 pub fn new(max_requests: u32, window_duration: std::time::Duration) -> Self {
104 Self {
105 rate_limiter: std::sync::Arc::new(tokio::sync::Mutex::new(
106 mocopr_core::utils::RateLimiter::new(max_requests, window_duration),
107 )),
108 }
109 }
110}
111
112#[async_trait::async_trait]
113impl Middleware for RateLimitMiddleware {
114 async fn before_request(&self, _request: &JsonRpcRequest) -> Result<()> {
115 let mut limiter = self.rate_limiter.lock().await;
116 if !limiter.check_rate_limit() {
117 return Err(Error::Protocol(
118 mocopr_core::error::ProtocolError::RateLimitExceeded,
119 ));
120 }
121 Ok(())
122 }
123
124 async fn after_response(
125 &self,
126 _request: &JsonRpcRequest,
127 _response: &JsonRpcResponse,
128 ) -> Result<()> {
129 Ok(())
130 }
131
132 async fn on_error(&self, _request: &JsonRpcRequest, _error: &Error) -> Result<()> {
133 Ok(())
134 }
135}
136
137pub struct AuthMiddleware {
139 api_keys: std::collections::HashSet<String>,
140}
141
142impl AuthMiddleware {
143 pub fn new() -> Self {
144 Self {
145 api_keys: std::collections::HashSet::new(),
146 }
147 }
148
149 pub fn with_api_key(mut self, key: String) -> Self {
150 self.api_keys.insert(key);
151 self
152 }
153
154 pub fn with_api_keys<I>(mut self, keys: I) -> Self
155 where
156 I: IntoIterator<Item = String>,
157 {
158 self.api_keys.extend(keys);
159 self
160 }
161}
162
163impl Default for AuthMiddleware {
164 fn default() -> Self {
165 Self::new()
166 }
167}
168
169#[async_trait::async_trait]
170impl Middleware for AuthMiddleware {
171 async fn before_request(&self, request: &JsonRpcRequest) -> Result<()> {
172 if self.api_keys.is_empty() {
173 return Ok(()); }
175
176 if let Some(params) = &request.params
178 && let Some(auth) = params.get("auth")
179 && let Some(api_key) = auth.get("api_key")
180 && let Some(key_str) = api_key.as_str()
181 && self.api_keys.contains(key_str)
182 {
183 return Ok(());
184 }
185 Err(Error::Protocol(
186 mocopr_core::error::ProtocolError::PermissionDenied,
187 ))
188 }
189
190 async fn after_response(
191 &self,
192 _request: &JsonRpcRequest,
193 _response: &JsonRpcResponse,
194 ) -> Result<()> {
195 Ok(())
196 }
197
198 async fn on_error(&self, _request: &JsonRpcRequest, _error: &Error) -> Result<()> {
199 Ok(())
200 }
201}
202
203pub struct MetricsMiddleware {
205 request_counts: std::sync::Arc<tokio::sync::RwLock<std::collections::HashMap<String, u64>>>,
206 response_times:
207 std::sync::Arc<tokio::sync::RwLock<std::collections::HashMap<String, Vec<u64>>>>,
208 request_start_times:
210 std::sync::Arc<tokio::sync::RwLock<std::collections::HashMap<String, std::time::Instant>>>,
211}
212
213impl MetricsMiddleware {
214 pub fn new() -> Self {
215 Self {
216 request_counts: std::sync::Arc::new(tokio::sync::RwLock::new(
217 std::collections::HashMap::new(),
218 )),
219 response_times: std::sync::Arc::new(tokio::sync::RwLock::new(
220 std::collections::HashMap::new(),
221 )),
222 request_start_times: std::sync::Arc::new(tokio::sync::RwLock::new(
223 std::collections::HashMap::new(),
224 )),
225 }
226 }
227
228 pub async fn get_metrics(&self) -> MetricsSnapshot {
229 let counts = self.request_counts.read().await;
230 let times = self.response_times.read().await;
231
232 MetricsSnapshot {
233 request_counts: counts.clone(),
234 average_response_times: times
235 .iter()
236 .map(|(method, times)| {
237 let avg = if times.is_empty() {
238 0.0
239 } else {
240 times.iter().sum::<u64>() as f64 / times.len() as f64
241 };
242 (method.clone(), avg)
243 })
244 .collect(),
245 }
246 }
247}
248
249impl Default for MetricsMiddleware {
250 fn default() -> Self {
251 Self::new()
252 }
253}
254
255#[derive(Debug, Clone)]
256pub struct MetricsSnapshot {
257 pub request_counts: std::collections::HashMap<String, u64>,
258 pub average_response_times: std::collections::HashMap<String, f64>,
259}
260
261#[async_trait::async_trait]
262impl Middleware for MetricsMiddleware {
263 async fn before_request(&self, request: &JsonRpcRequest) -> Result<()> {
264 let mut counts = self.request_counts.write().await;
266 *counts.entry(request.method.clone()).or_insert(0) += 1;
267
268 let request_key = request
270 .id
271 .as_ref()
272 .map(|id| match id {
273 RequestId::String(s) => s.clone(),
274 RequestId::Number(n) => n.to_string(),
275 })
276 .unwrap_or_else(|| request.method.clone());
277
278 let mut start_times = self.request_start_times.write().await;
279 start_times.insert(request_key, std::time::Instant::now());
280
281 Ok(())
282 }
283
284 async fn after_response(
285 &self,
286 request: &JsonRpcRequest,
287 _response: &JsonRpcResponse,
288 ) -> Result<()> {
289 let request_key = request
291 .id
292 .as_ref()
293 .map(|id| match id {
294 RequestId::String(s) => s.clone(),
295 RequestId::Number(n) => n.to_string(),
296 })
297 .unwrap_or_else(|| request.method.clone());
298
299 let mut start_times = self.request_start_times.write().await;
300 if let Some(start_time) = start_times.remove(&request_key) {
301 let elapsed = start_time.elapsed();
302 let elapsed_ms = elapsed.as_millis() as u64;
303
304 let mut times = self.response_times.write().await;
305 times
306 .entry(request.method.clone())
307 .or_insert_with(Vec::new)
308 .push(elapsed_ms);
309 } else {
310 warn!(
312 "No start time found for request: {} (method: {})",
313 request_key, request.method
314 );
315 }
316
317 Ok(())
318 }
319
320 async fn on_error(&self, _request: &JsonRpcRequest, _error: &Error) -> Result<()> {
321 Ok(())
322 }
323}