1use std::collections::HashMap;
6use std::sync::Arc;
7
8use serde_json;
9
10use crate::errors::HttpError;
11use crate::middleware::v2::{Middleware, Next, NextFuture};
12use crate::request::ElifRequest;
13use crate::response::ElifResponse;
14use elif_core::container::{IocContainer, ScopeId};
15
16pub trait IocMiddleware: Middleware {
18 fn from_ioc_container(
20 container: &IocContainer,
21 scope: Option<&ScopeId>,
22 ) -> Result<Self, String>
23 where
24 Self: Sized;
25}
26
27pub struct IocMiddlewareFactory<M> {
29 _phantom: std::marker::PhantomData<M>,
30}
31
32impl<M> IocMiddlewareFactory<M> {
33 pub fn new() -> Self {
34 Self {
35 _phantom: std::marker::PhantomData,
36 }
37 }
38}
39
40impl<M> Default for IocMiddlewareFactory<M> {
41 fn default() -> Self {
42 Self::new()
43 }
44}
45
46impl<M> IocMiddlewareFactory<M>
47where
48 M: IocMiddleware + 'static,
49{
50 pub fn create(
52 &self,
53 container: &IocContainer,
54 scope: Option<&ScopeId>,
55 ) -> Result<M, HttpError> {
56 M::from_ioc_container(container, scope).map_err(|e| HttpError::InternalError {
57 message: format!("Failed to create middleware: {}", e),
58 })
59 }
60}
61
62pub struct MiddlewareRegistry {
64 factories: HashMap<String, Box<dyn MiddlewareFactory>>,
65 container: Arc<IocContainer>,
66}
67
68pub trait MiddlewareFactory: Send + Sync {
70 fn create_middleware(
72 &self,
73 container: &IocContainer,
74 scope: Option<&ScopeId>,
75 ) -> Result<Arc<dyn Middleware>, HttpError>;
76}
77
78impl<M> MiddlewareFactory for IocMiddlewareFactory<M>
79where
80 M: IocMiddleware + 'static,
81{
82 fn create_middleware(
83 &self,
84 container: &IocContainer,
85 scope: Option<&ScopeId>,
86 ) -> Result<Arc<dyn Middleware>, HttpError> {
87 let middleware = self.create(container, scope)?;
88 Ok(Arc::new(middleware))
89 }
90}
91
92impl MiddlewareRegistry {
93 pub fn new(container: Arc<IocContainer>) -> Self {
95 Self {
96 factories: HashMap::new(),
97 container,
98 }
99 }
100
101 pub fn register<M>(&mut self, name: &str) -> Result<(), HttpError>
103 where
104 M: IocMiddleware + 'static,
105 {
106 let factory = Box::new(IocMiddlewareFactory::<M>::new());
107 self.factories.insert(name.to_string(), factory);
108 Ok(())
109 }
110
111 pub fn register_factory(&mut self, name: &str, factory: Box<dyn MiddlewareFactory>) {
113 self.factories.insert(name.to_string(), factory);
114 }
115
116 pub fn create_middleware(
118 &self,
119 name: &str,
120 scope: Option<&ScopeId>,
121 ) -> Result<Arc<dyn Middleware>, HttpError> {
122 let factory = self
123 .factories
124 .get(name)
125 .ok_or_else(|| HttpError::InternalError {
126 message: format!("Middleware '{}' not registered", name),
127 })?;
128
129 factory.create_middleware(&self.container, scope)
130 }
131
132 pub fn create_middleware_pipeline(
134 &self,
135 names: &[&str],
136 scope: Option<&ScopeId>,
137 ) -> Result<Vec<Arc<dyn Middleware>>, HttpError> {
138 names
139 .iter()
140 .map(|name| self.create_middleware(name, scope))
141 .collect()
142 }
143
144 pub fn registered_middleware(&self) -> Vec<String> {
146 self.factories.keys().cloned().collect()
147 }
148}
149
150pub struct MiddlewareRegistryBuilder {
152 container: Option<Arc<IocContainer>>,
153 middleware: Vec<(String, Box<dyn MiddlewareFactory>)>,
154}
155
156impl MiddlewareRegistryBuilder {
157 pub fn new() -> Self {
159 Self {
160 container: None,
161 middleware: Vec::new(),
162 }
163 }
164
165 pub fn container(mut self, container: Arc<IocContainer>) -> Self {
167 self.container = Some(container);
168 self
169 }
170
171 pub fn register<M>(mut self, name: &str) -> Self
173 where
174 M: IocMiddleware + 'static,
175 {
176 let factory = Box::new(IocMiddlewareFactory::<M>::new());
177 self.middleware.push((name.to_string(), factory));
178 self
179 }
180
181 pub fn register_factory(mut self, name: &str, factory: Box<dyn MiddlewareFactory>) -> Self {
183 self.middleware.push((name.to_string(), factory));
184 self
185 }
186
187 pub fn build(self) -> Result<MiddlewareRegistry, HttpError> {
189 let container = self.container.ok_or_else(|| HttpError::InternalError {
190 message: "IoC container is required for middleware registry".to_string(),
191 })?;
192
193 let mut registry = MiddlewareRegistry::new(container);
194
195 for (name, factory) in self.middleware {
196 registry.register_factory(&name, factory);
197 }
198
199 Ok(registry)
200 }
201}
202
203impl Default for MiddlewareRegistryBuilder {
204 fn default() -> Self {
205 Self::new()
206 }
207}
208
209pub struct LazyIocMiddleware {
211 middleware_name: String,
212 registry: Arc<MiddlewareRegistry>,
213}
214
215impl std::fmt::Debug for LazyIocMiddleware {
216 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
217 f.debug_struct("LazyIocMiddleware")
218 .field("middleware_name", &self.middleware_name)
219 .finish()
220 }
221}
222
223impl LazyIocMiddleware {
224 pub fn new(middleware_name: String, registry: Arc<MiddlewareRegistry>) -> Self {
226 Self {
227 middleware_name,
228 registry,
229 }
230 }
231}
232
233impl Middleware for LazyIocMiddleware {
234 fn handle(&self, request: ElifRequest, next: Next) -> NextFuture<'static> {
235 let middleware_name = self.middleware_name.clone();
236 let registry = self.registry.clone();
237
238 Box::pin(async move {
239 let scope_result = registry.container.create_scope();
241 let scope = scope_result.ok();
242
243 match registry.create_middleware(&middleware_name, scope.as_ref()) {
245 Ok(middleware) => {
246 let result = middleware.handle(request, next).await;
248
249 if let Some(scope_id) = scope {
251 let _ = registry.container.dispose_scope(&scope_id).await;
252 }
253
254 result
255 }
256 Err(e) => {
257 eprintln!(
259 "CRITICAL: Failed to instantiate middleware '{}': {:?}",
260 middleware_name, e
261 );
262
263 if let Some(scope_id) = scope {
265 let _ = registry.container.dispose_scope(&scope_id).await;
266 }
267
268 ElifResponse::internal_server_error()
270 .json(&serde_json::json!({
271 "error": {
272 "code": "MIDDLEWARE_INIT_FAILED",
273 "message": "Internal server error",
274 "hint": "A required middleware component failed to initialize"
275 }
276 }))
277 .unwrap_or_else(|_| ElifResponse::internal_server_error())
278 }
279 }
280 })
281 }
282
283 fn name(&self) -> &'static str {
284 "LazyIocMiddleware"
285 }
286}
287
288#[derive(Clone, Debug)]
290pub struct MiddlewareContext {
291 pub request_id: String,
292 pub user_id: Option<String>,
293 pub session_id: Option<String>,
294 pub correlation_id: Option<String>,
295 pub custom_data: HashMap<String, String>,
296}
297
298impl MiddlewareContext {
299 pub fn from_request(request: &ElifRequest) -> Self {
301 Self {
302 request_id: request
303 .header("x-request-id")
304 .and_then(|h| h.to_str().ok())
305 .unwrap_or("unknown")
306 .to_string(),
307 user_id: request
308 .header("x-user-id")
309 .and_then(|h| h.to_str().ok())
310 .map(String::from),
311 session_id: request
312 .header("x-session-id")
313 .and_then(|h| h.to_str().ok())
314 .map(String::from),
315 correlation_id: request
316 .header("x-correlation-id")
317 .and_then(|h| h.to_str().ok())
318 .map(String::from),
319 custom_data: HashMap::new(),
320 }
321 }
322
323 pub fn with_data(mut self, key: String, value: String) -> Self {
325 self.custom_data.insert(key, value);
326 self
327 }
328}
329
330pub struct MiddlewareGroup {
332 name: String,
333 middleware_names: Vec<String>,
334 registry: Arc<MiddlewareRegistry>,
335}
336
337impl MiddlewareGroup {
338 pub fn new(
340 name: String,
341 middleware_names: Vec<String>,
342 registry: Arc<MiddlewareRegistry>,
343 ) -> Self {
344 Self {
345 name,
346 middleware_names,
347 registry,
348 }
349 }
350
351 pub fn create_middleware(
353 &self,
354 scope: Option<&ScopeId>,
355 ) -> Result<Vec<Arc<dyn Middleware>>, HttpError> {
356 self.middleware_names
357 .iter()
358 .map(|name| self.registry.create_middleware(name, scope))
359 .collect()
360 }
361
362 pub fn name(&self) -> &str {
364 &self.name
365 }
366
367 pub fn middleware_names(&self) -> &[String] {
369 &self.middleware_names
370 }
371}
372
373#[cfg(test)]
374mod tests {
375 use super::*;
376 use crate::middleware::v2::Middleware;
377 use elif_core::container::{IocContainer, ServiceBinder};
378
379 #[derive(Default, Clone, Debug)]
381 pub struct TestLoggerService {
382 pub name: String,
383 }
384
385 unsafe impl Send for TestLoggerService {}
386 unsafe impl Sync for TestLoggerService {}
387
388 #[derive(Debug)]
390 pub struct TestIocMiddleware {
391 logger: Arc<TestLoggerService>,
392 }
393
394 impl IocMiddleware for TestIocMiddleware {
395 fn from_ioc_container(
396 container: &IocContainer,
397 _scope: Option<&ScopeId>,
398 ) -> Result<Self, String> {
399 let logger = container
400 .resolve::<TestLoggerService>()
401 .map_err(|e| format!("Failed to resolve TestLoggerService: {}", e))?;
402
403 Ok(Self { logger })
404 }
405 }
406
407 impl Middleware for TestIocMiddleware {
408 fn handle(&self, request: ElifRequest, next: Next) -> NextFuture<'static> {
409 let logger_name = self.logger.name.clone();
411 Box::pin(async move {
412 println!("TestIocMiddleware: Using logger: {}", logger_name);
414 next.run(request).await
415 })
416 }
417
418 fn name(&self) -> &'static str {
419 "TestIocMiddleware"
420 }
421 }
422
423 #[tokio::test]
424 async fn test_ioc_middleware_creation() {
425 let mut container = IocContainer::new();
426
427 let logger_service = TestLoggerService {
429 name: "TestLogger".to_string(),
430 };
431 container.bind_instance::<TestLoggerService, TestLoggerService>(logger_service);
432 container.build().expect("Container build failed");
433
434 let container_arc = Arc::new(container);
435 let mut registry = MiddlewareRegistry::new(container_arc);
436
437 registry
439 .register::<TestIocMiddleware>("test_middleware")
440 .expect("Failed to register middleware");
441
442 let middleware = registry
444 .create_middleware("test_middleware", None)
445 .expect("Failed to create middleware");
446
447 assert_eq!(middleware.name(), "TestIocMiddleware");
448 }
449
450 #[tokio::test]
451 async fn test_middleware_registry_builder() {
452 let mut container = IocContainer::new();
453 container.bind::<TestLoggerService, TestLoggerService>();
454 container.build().expect("Container build failed");
455
456 let registry = MiddlewareRegistryBuilder::new()
457 .container(Arc::new(container))
458 .register::<TestIocMiddleware>("test_ioc")
459 .build()
460 .expect("Failed to build middleware registry");
461
462 let registered = registry.registered_middleware();
463 assert!(registered.contains(&"test_ioc".to_string()));
464
465 let middleware = registry
466 .create_middleware("test_ioc", None)
467 .expect("Failed to create middleware");
468
469 assert_eq!(middleware.name(), "TestIocMiddleware");
470 }
471
472 #[tokio::test]
473 async fn test_middleware_pipeline_creation() {
474 let mut container = IocContainer::new();
475 container.bind::<TestLoggerService, TestLoggerService>();
476 container.build().expect("Container build failed");
477
478 let registry = MiddlewareRegistryBuilder::new()
479 .container(Arc::new(container))
480 .register::<TestIocMiddleware>("ioc1")
481 .register::<TestIocMiddleware>("ioc2")
482 .build()
483 .expect("Failed to build middleware registry");
484
485 let middleware_pipeline = registry
486 .create_middleware_pipeline(&["ioc1", "ioc2"], None)
487 .expect("Failed to create middleware pipeline");
488
489 assert_eq!(middleware_pipeline.len(), 2);
490 }
491
492 #[tokio::test]
493 async fn test_lazy_ioc_middleware() {
494 use crate::request::method::ElifMethod as HttpMethod;
495 use crate::response::headers::ElifHeaderMap;
496
497 let mut container = IocContainer::new();
498 container.bind::<TestLoggerService, TestLoggerService>();
499 container.build().expect("Container build failed");
500
501 let registry = Arc::new(
502 MiddlewareRegistryBuilder::new()
503 .container(Arc::new(container))
504 .register::<TestIocMiddleware>("lazy_test")
505 .build()
506 .expect("Failed to build middleware registry"),
507 );
508
509 let lazy_middleware = LazyIocMiddleware::new("lazy_test".to_string(), registry);
510
511 let request = ElifRequest::new(
512 HttpMethod::GET,
513 "/test".parse().unwrap(),
514 ElifHeaderMap::new(),
515 );
516
517 let next = Next::new(|_req| Box::pin(async { ElifResponse::ok().text("Success") }));
518
519 let response = lazy_middleware.handle(request, next).await;
520 assert_eq!(
521 response.status_code(),
522 crate::response::status::ElifStatusCode::OK
523 );
524 }
525
526 #[tokio::test]
527 async fn test_lazy_ioc_middleware_instantiation_failure() {
528 use crate::request::method::ElifMethod as HttpMethod;
529 use crate::response::headers::ElifHeaderMap;
530
531 let container = IocContainer::new();
533 let registry = Arc::new(
536 MiddlewareRegistryBuilder::new()
537 .container(Arc::new(container))
538 .register::<TestIocMiddleware>("failing_middleware")
539 .build()
540 .expect("Failed to build middleware registry"),
541 );
542
543 let lazy_middleware = LazyIocMiddleware::new("failing_middleware".to_string(), registry);
544
545 let request = ElifRequest::new(
546 HttpMethod::GET,
547 "/test".parse().unwrap(),
548 ElifHeaderMap::new(),
549 );
550
551 let next = Next::new(|_req| {
552 Box::pin(async {
553 panic!("Next middleware should not be called when middleware instantiation fails!");
555 })
556 });
557
558 let response = lazy_middleware.handle(request, next).await;
559
560 assert_eq!(
562 response.status_code(),
563 crate::response::status::ElifStatusCode::INTERNAL_SERVER_ERROR
564 );
565
566 }
569
570 #[tokio::test]
571 async fn test_middleware_context_from_request() {
572 use crate::request::method::ElifMethod as HttpMethod;
573 use crate::response::headers::{ElifHeaderMap, ElifHeaderName, ElifHeaderValue};
574
575 let mut headers = ElifHeaderMap::new();
576 headers.insert(
577 ElifHeaderName::from_str("x-request-id").unwrap(),
578 ElifHeaderValue::from_str("req-123").unwrap(),
579 );
580 headers.insert(
581 ElifHeaderName::from_str("x-user-id").unwrap(),
582 ElifHeaderValue::from_str("user-456").unwrap(),
583 );
584
585 let request = ElifRequest::new(HttpMethod::POST, "/api/test".parse().unwrap(), headers);
586
587 let context = MiddlewareContext::from_request(&request);
588
589 assert_eq!(context.request_id, "req-123");
590 assert_eq!(context.user_id, Some("user-456".to_string()));
591 assert!(context.session_id.is_none());
592 }
593
594 #[tokio::test]
595 async fn test_middleware_group() {
596 let mut container = IocContainer::new();
597 container.bind::<TestLoggerService, TestLoggerService>();
598 container.build().expect("Container build failed");
599
600 let registry = Arc::new(
601 MiddlewareRegistryBuilder::new()
602 .container(Arc::new(container))
603 .register::<TestIocMiddleware>("group1")
604 .register::<TestIocMiddleware>("group2")
605 .build()
606 .expect("Failed to build middleware registry"),
607 );
608
609 let group = MiddlewareGroup::new(
610 "test_group".to_string(),
611 vec!["group1".to_string(), "group2".to_string()],
612 registry,
613 );
614
615 assert_eq!(group.name(), "test_group");
616 assert_eq!(group.middleware_names().len(), 2);
617
618 let middleware = group
619 .create_middleware(None)
620 .expect("Failed to create group middleware");
621
622 assert_eq!(middleware.len(), 2);
623 }
624}