1use std::{collections::HashMap, future::Future};
7
8pub mod adapter;
9pub mod builder;
10#[cfg(feature = "router")]
11pub mod config;
12pub mod contract;
13pub mod docs;
14pub mod graphiql;
15pub mod graphql;
16pub mod grpc;
17pub mod grpc_explorer;
18pub mod handler;
19pub mod metadata;
20pub mod method;
21pub mod openapi;
22pub mod rest;
23pub mod scalar;
24pub mod schema;
25
26#[cfg(feature = "router-graphql")]
28pub mod graphql_prod;
29#[cfg(feature = "router-grpc")]
30pub mod grpc_prod;
31
32pub use adapter::ProtocolAdapter;
33pub use builder::RouteBuilder;
34#[cfg(feature = "router")]
35pub use config::{GraphQLConfig, GrpcConfig, RestConfig, RouterConfig, ServerConfig};
36pub use contract::{
37 ContractTestConfig, ContractTestResult, ContractTestResults, ContractTestable, ContractTester,
38};
39pub use docs::DocsConfig;
40pub use graphiql::{graphiql_html, GraphiQLConfig, GraphiQLTheme};
41pub use graphql::{GraphQLAdapter, GraphQLOperation, OperationType};
42#[cfg(feature = "router-graphql")]
44pub use graphql_prod::GraphQLProductionAdapter;
45pub use grpc::{GrpcAdapter, GrpcMethod, GrpcMethodType, GrpcRequest, GrpcStatus};
46pub use grpc_explorer::{grpc_explorer_html, GrpcExplorerConfig, GrpcExplorerTheme};
47#[cfg(feature = "router-grpc")]
48pub use grpc_prod::{protobuf, status, streaming, GrpcProductionAdapter, GrpcService};
49pub use handler::{Handler, HandlerFn};
50pub use metadata::RouteMetadata;
51pub use method::Method;
52pub use openapi::{OpenApiGenerator, OpenApiServer};
53pub use rest::{RestAdapter, RestRequest, RestResponse, RestRoute};
54pub use scalar::{scalar_html, ScalarConfig, ScalarLayout, ScalarTheme};
55pub use schema::ToJsonSchema;
56
57pub struct Router {
62 handlers: HashMap<String, Box<dyn Handler>>,
63 adapters: HashMap<String, Box<dyn ProtocolAdapter>>,
64 routes: Vec<RouteMetadata>,
65 #[cfg(feature = "router")]
66 #[allow(dead_code)]
67 config: Option<RouterConfig>,
68}
69
70impl Router {
71 pub fn new() -> Self {
73 Self {
74 handlers: HashMap::new(),
75 adapters: HashMap::new(),
76 routes: Vec::new(),
77 #[cfg(feature = "router")]
78 config: None,
79 }
80 }
81
82 #[cfg(feature = "router")]
84 pub fn with_config(config: RouterConfig) -> Self {
85 let mut router = Self {
86 handlers: HashMap::new(),
87 adapters: HashMap::new(),
88 routes: Vec::new(),
89 config: Some(config.clone()),
90 };
91
92 if config.has_protocol("rest") {
94 router.add_adapter(Box::new(RestAdapter::new()));
95 }
96 if config.has_protocol("graphql") {
97 router.add_adapter(Box::new(GraphQLAdapter::new()));
98 }
99 if config.has_protocol("grpc") {
100 router.add_adapter(Box::new(GrpcAdapter::new()));
101 }
102
103 router
104 }
105
106 pub fn register<F, Fut>(&mut self, name: &str, handler: F)
108 where
109 F: Fn() -> Fut + Send + Sync + 'static,
110 Fut: Future<Output = String> + Send + 'static,
111 {
112 self.handlers
113 .insert(name.to_string(), Box::new(HandlerFn::new(handler)));
114 }
115
116 pub fn handlers_count(&self) -> usize {
118 self.handlers.len()
119 }
120
121 pub fn add_adapter(&mut self, adapter: Box<dyn ProtocolAdapter>) {
123 self.adapters.insert(adapter.name().to_string(), adapter);
124 }
125
126 pub fn has_adapter(&self, name: &str) -> bool {
128 self.adapters.contains_key(name)
129 }
130
131 pub fn get_adapter(&self, name: &str) -> Option<&dyn ProtocolAdapter> {
133 self.adapters.get(name).map(|b| &**b)
134 }
135
136 pub async fn route_request(&self, protocol: &str, request: &str) -> Result<String, String> {
138 let adapter = self
139 .get_adapter(protocol)
140 .ok_or_else(|| format!("Adapter not found: {}", protocol))?;
141
142 adapter.handle(request).await
143 }
144
145 pub async fn execute(&self, name: &str) -> Result<String, String> {
147 match self.handlers.get(name) {
148 Some(handler) => handler.call().await,
149 None => Err(format!("Handler '{}' not found", name)),
150 }
151 }
152
153 pub fn list_handlers(&self) -> Vec<String> {
158 self.handlers.keys().cloned().collect()
159 }
160
161 pub async fn call_handler(&self, name: &str, _request: &str) -> Result<String, String> {
166 self.execute(name).await
169 }
170
171 pub fn can_handle_rest(&self, _name: &str) -> bool {
173 self.has_adapter("rest")
174 }
175
176 pub fn can_handle_graphql(&self, _name: &str) -> bool {
178 self.has_adapter("graphql")
179 }
180
181 pub fn can_handle_grpc(&self, _name: &str) -> bool {
183 self.has_adapter("grpc")
184 }
185
186 pub fn enabled_protocols(&self) -> Vec<String> {
188 self.adapters.keys().cloned().collect()
189 }
190
191 pub fn add_route(&mut self, metadata: RouteMetadata) {
196 self.routes.push(metadata);
197 }
198
199 pub fn routes(&self) -> &[RouteMetadata] {
204 &self.routes
205 }
206
207 pub fn get<F, Fut>(&mut self, path: &str, handler: F)
213 where
214 F: Fn() -> Fut + Send + Sync + 'static,
215 Fut: Future<Output = String> + Send + 'static,
216 {
217 let handler_name = format!("GET:{}", path);
218 self.register(&handler_name, handler);
219 self.add_route(RouteMetadata::new(path, Method::GET, "rest"));
220 }
221
222 pub fn post<F, Fut>(&mut self, path: &str, handler: F)
228 where
229 F: Fn() -> Fut + Send + Sync + 'static,
230 Fut: Future<Output = String> + Send + 'static,
231 {
232 let handler_name = format!("POST:{}", path);
233 self.register(&handler_name, handler);
234 self.add_route(RouteMetadata::new(path, Method::POST, "rest"));
235 }
236
237 pub fn put<F, Fut>(&mut self, path: &str, handler: F)
243 where
244 F: Fn() -> Fut + Send + Sync + 'static,
245 Fut: Future<Output = String> + Send + 'static,
246 {
247 let handler_name = format!("PUT:{}", path);
248 self.register(&handler_name, handler);
249 self.add_route(RouteMetadata::new(path, Method::PUT, "rest"));
250 }
251
252 pub fn delete<F, Fut>(&mut self, path: &str, handler: F)
258 where
259 F: Fn() -> Fut + Send + Sync + 'static,
260 Fut: Future<Output = String> + Send + 'static,
261 {
262 let handler_name = format!("DELETE:{}", path);
263 self.register(&handler_name, handler);
264 self.add_route(RouteMetadata::new(path, Method::DELETE, "rest"));
265 }
266
267 pub fn patch<F, Fut>(&mut self, path: &str, handler: F)
273 where
274 F: Fn() -> Fut + Send + Sync + 'static,
275 Fut: Future<Output = String> + Send + 'static,
276 {
277 let handler_name = format!("PATCH:{}", path);
278 self.register(&handler_name, handler);
279 self.add_route(RouteMetadata::new(path, Method::PATCH, "rest"));
280 }
281
282 pub fn head<F, Fut>(&mut self, path: &str, handler: F)
288 where
289 F: Fn() -> Fut + Send + Sync + 'static,
290 Fut: Future<Output = String> + Send + 'static,
291 {
292 let handler_name = format!("HEAD:{}", path);
293 self.register(&handler_name, handler);
294 self.add_route(RouteMetadata::new(path, Method::HEAD, "rest"));
295 }
296
297 pub fn options<F, Fut>(&mut self, path: &str, handler: F)
303 where
304 F: Fn() -> Fut + Send + Sync + 'static,
305 Fut: Future<Output = String> + Send + 'static,
306 {
307 let handler_name = format!("OPTIONS:{}", path);
308 self.register(&handler_name, handler);
309 self.add_route(RouteMetadata::new(path, Method::OPTIONS, "rest"));
310 }
311
312 pub async fn call_rest(&self, method: &str, path: &str) -> Result<String, String> {
314 let adapter = self
315 .adapters
316 .get("rest")
317 .ok_or_else(|| "REST adapter not enabled".to_string())?;
318
319 let request = format!("{} {}", method, path);
320 adapter.handle(&request).await
321 }
322
323 pub async fn call_graphql(&self, query: &str) -> Result<String, String> {
325 let adapter = self
326 .adapters
327 .get("graphql")
328 .ok_or_else(|| "GraphQL adapter not enabled".to_string())?;
329
330 adapter.handle(query).await
331 }
332
333 pub async fn call_grpc(&self, method: &str, request: &str) -> Result<String, String> {
335 let adapter = self
336 .adapters
337 .get("grpc")
338 .ok_or_else(|| "gRPC adapter not enabled".to_string())?;
339
340 let grpc_request = format!("{}:{}", method, request);
341 adapter.handle(&grpc_request).await
342 }
343
344 pub fn scalar(&self, title: &str, version: &str) -> String {
366 let config = scalar::ScalarConfig::default();
367 self.scalar_docs(config, title, version)
368 }
369
370 pub fn scalar_docs(&self, config: scalar::ScalarConfig, title: &str, version: &str) -> String {
396 let spec = OpenApiGenerator::new(title, version).generate(self);
398 let spec_json = serde_json::to_string(&spec).unwrap_or_else(|_| "{}".to_string());
399
400 scalar::scalar_html(&config, title, &spec_json)
402 }
403}
404
405impl Default for Router {
406 fn default() -> Self {
407 Self::new()
408 }
409}
410
411#[cfg(test)]
412mod tests {
413 use super::*;
414
415 #[tokio::test]
416 async fn test_router_creation() {
417 let router = Router::new();
418 assert_eq!(router.handlers_count(), 0);
419 }
420
421 #[tokio::test]
422 async fn test_handler_registration() {
423 let mut router = Router::new();
424 router.register("test", || async { "Hello".to_string() });
425 assert_eq!(router.handlers_count(), 1);
426 }
427
428 #[tokio::test]
429 async fn test_handler_execution() {
430 let mut router = Router::new();
431 router.register("test", || async { "Hello".to_string() });
432 let result = router.execute("test").await;
433 assert_eq!(result, Ok("Hello".to_string()));
434 }
435
436 #[tokio::test]
438 async fn test_router_starts_with_no_routes() {
439 let router = Router::new();
440 let routes = router.routes();
441 assert_eq!(routes.len(), 0);
442 }
443
444 #[tokio::test]
445 async fn test_add_route_metadata() {
446 let mut router = Router::new();
447 let metadata = RouteMetadata::new("/users", "GET", "rest");
448
449 router.add_route(metadata.clone());
450
451 let routes = router.routes();
452 assert_eq!(routes.len(), 1);
453 assert_eq!(routes[0].path, "/users");
454 assert_eq!(routes[0].method, "GET");
455 assert_eq!(routes[0].protocol, "rest");
456 }
457
458 #[tokio::test]
459 async fn test_add_multiple_routes() {
460 let mut router = Router::new();
461
462 router.add_route(RouteMetadata::new("/users", "GET", "rest"));
463 router.add_route(RouteMetadata::new("/users", "POST", "rest"));
464 router.add_route(RouteMetadata::new("/posts", "GET", "rest"));
465
466 let routes = router.routes();
467 assert_eq!(routes.len(), 3);
468 }
469
470 #[tokio::test]
471 async fn test_routes_with_different_protocols() {
472 let mut router = Router::new();
473
474 router.add_route(RouteMetadata::new("/users", "GET", "rest"));
475 router.add_route(RouteMetadata::new("users", "query", "graphql"));
476 router.add_route(RouteMetadata::new("UserService.GetUser", "unary", "grpc"));
477
478 let routes = router.routes();
479 assert_eq!(routes.len(), 3);
480
481 assert_eq!(routes[0].protocol, "rest");
482 assert_eq!(routes[1].protocol, "graphql");
483 assert_eq!(routes[2].protocol, "grpc");
484 }
485
486 #[tokio::test]
487 async fn test_routes_returns_immutable_reference() {
488 let mut router = Router::new();
489 router.add_route(RouteMetadata::new("/test", "GET", "rest"));
490
491 let routes1 = router.routes();
492 let routes2 = router.routes();
493
494 assert_eq!(routes1.len(), routes2.len());
496 assert_eq!(routes1[0].path, routes2[0].path);
497 }
498
499 #[tokio::test]
501 async fn test_route_get_method() {
502 let mut router = Router::new();
503 router.get("/users", || async { "User list".to_string() });
504
505 let routes = router.routes();
506 assert_eq!(routes.len(), 1);
507 assert_eq!(routes[0].path, "/users");
508 assert_eq!(routes[0].method, "GET");
509 assert_eq!(routes[0].protocol, "rest");
510 }
511
512 #[tokio::test]
513 async fn test_route_post_method() {
514 let mut router = Router::new();
515 router.post("/users", || async { "User created".to_string() });
516
517 let routes = router.routes();
518 assert_eq!(routes.len(), 1);
519 assert_eq!(routes[0].path, "/users");
520 assert_eq!(routes[0].method, "POST");
521 assert_eq!(routes[0].protocol, "rest");
522 }
523
524 #[tokio::test]
525 async fn test_route_put_method() {
526 let mut router = Router::new();
527 router.put("/users/1", || async { "User updated".to_string() });
528
529 let routes = router.routes();
530 assert_eq!(routes.len(), 1);
531 assert_eq!(routes[0].method, "PUT");
532 }
533
534 #[tokio::test]
535 async fn test_route_delete_method() {
536 let mut router = Router::new();
537 router.delete("/users/1", || async { "User deleted".to_string() });
538
539 let routes = router.routes();
540 assert_eq!(routes.len(), 1);
541 assert_eq!(routes[0].method, "DELETE");
542 }
543
544 #[tokio::test]
545 async fn test_route_patch_method() {
546 let mut router = Router::new();
547 router.patch("/users/1", || async { "User patched".to_string() });
548
549 let routes = router.routes();
550 assert_eq!(routes.len(), 1);
551 assert_eq!(routes[0].method, "PATCH");
552 }
553
554 #[tokio::test]
555 async fn test_multiple_routes_different_methods() {
556 let mut router = Router::new();
557 router.get("/users", || async { "List".to_string() });
558 router.post("/users", || async { "Create".to_string() });
559 router.put("/users/1", || async { "Update".to_string() });
560 router.delete("/users/1", || async { "Delete".to_string() });
561
562 let routes = router.routes();
563 assert_eq!(routes.len(), 4);
564
565 assert_eq!(routes[0].method, "GET");
566 assert_eq!(routes[1].method, "POST");
567 assert_eq!(routes[2].method, "PUT");
568 assert_eq!(routes[3].method, "DELETE");
569 }
570
571 #[tokio::test]
572 async fn test_route_method_with_path_params() {
573 let mut router = Router::new();
574 router.get("/users/{id}", || async { "User details".to_string() });
575 router.get("/users/{id}/posts/{post_id}", || async {
576 "Post details".to_string()
577 });
578
579 let routes = router.routes();
580 assert_eq!(routes.len(), 2);
581 assert_eq!(routes[0].path, "/users/{id}");
582 assert_eq!(routes[1].path, "/users/{id}/posts/{post_id}");
583 }
584
585 #[tokio::test]
586 async fn test_route_registration_and_execution() {
587 let mut router = Router::new();
588 router.get("/test", || async { "GET response".to_string() });
589 router.post("/test", || async { "POST response".to_string() });
590
591 assert_eq!(router.routes().len(), 2);
593 assert_eq!(router.handlers_count(), 2);
594
595 let result1 = router.execute("GET:/test").await;
597 let result2 = router.execute("POST:/test").await;
598
599 assert_eq!(result1, Ok("GET response".to_string()));
600 assert_eq!(result2, Ok("POST response".to_string()));
601 }
602
603 #[tokio::test]
605 async fn test_scalar_generates_html() {
606 let mut router = Router::new();
607 router.get("/users", || async { "Users".to_string() });
608
609 let html = router.scalar("Test API", "1.0.0");
610
611 assert!(html.contains("<!DOCTYPE html>"));
612 assert!(html.contains("<title>Test API - API Documentation</title>"));
613 assert!(html.contains("@scalar/api-reference"));
614 }
615
616 #[tokio::test]
617 async fn test_scalar_contains_openapi_spec() {
618 let mut router = Router::new();
619 router.get("/users", || async { "Users".to_string() });
620 router.post("/users", || async { "User created".to_string() });
621
622 let html = router.scalar("Test API", "1.0.0");
623
624 assert!(html.contains("openapi"));
626 assert!(html.contains("Test API"));
627 assert!(html.contains("1.0.0"));
628 }
629
630 #[tokio::test]
631 async fn test_scalar_docs_with_custom_config() {
632 let mut router = Router::new();
633 router.get("/users", || async { "Users".to_string() });
634
635 let config = scalar::ScalarConfig::new()
636 .theme(scalar::ScalarTheme::Light)
637 .show_sidebar(false);
638
639 let html = router.scalar_docs(config, "Custom API", "2.0.0");
640
641 assert!(html.contains("Custom API"));
642 assert!(html.contains(r#""theme":"light""#));
643 assert!(html.contains(r#""showSidebar":false"#));
644 }
645
646 #[tokio::test]
647 async fn test_scalar_docs_with_custom_css() {
648 let mut router = Router::new();
649 router.get("/test", || async { "Test".to_string() });
650
651 let config = scalar::ScalarConfig::new().custom_css("body { font-family: 'Inter'; }");
652
653 let html = router.scalar_docs(config, "API", "1.0");
654
655 assert!(html.contains("<style>body { font-family: 'Inter'; }</style>"));
656 }
657
658 #[tokio::test]
659 async fn test_scalar_with_multiple_routes() {
660 let mut router = Router::new();
661 router.get("/users", || async { "Users".to_string() });
662 router.post("/users", || async { "Create".to_string() });
663 router.get("/users/{id}", || async { "User details".to_string() });
664 router.delete("/users/{id}", || async { "Delete".to_string() });
665
666 let html = router.scalar("API", "1.0.0");
667
668 assert!(html.contains("/users"));
670 }
671
672 #[tokio::test]
674 async fn test_get_adapter_returns_adapter() {
675 let mut router = Router::new();
676 router.add_adapter(Box::new(RestAdapter::new()));
677
678 let adapter = router.get_adapter("rest");
679 assert!(adapter.is_some());
680 assert_eq!(adapter.unwrap().name(), "rest");
681 }
682
683 #[tokio::test]
684 async fn test_get_adapter_returns_none_for_missing() {
685 let router = Router::new();
686 let adapter = router.get_adapter("rest");
687 assert!(adapter.is_none());
688 }
689
690 #[tokio::test]
691 async fn test_route_request_success() {
692 let mut router = Router::new();
693 router.register("test_handler", || async { "Success!".to_string() });
694
695 let mut rest_adapter = RestAdapter::new();
697 rest_adapter.route("GET", "/test", "test_handler");
698 router.add_adapter(Box::new(rest_adapter));
699
700 let result = router.route_request("rest", "GET /test").await;
701 assert!(result.is_ok());
702 let response = result.unwrap();
703 assert!(response.contains("HTTP 200") || response.contains("test_handler"));
704 }
705
706 #[tokio::test]
707 async fn test_route_request_unknown_adapter() {
708 let router = Router::new();
709 let result = router.route_request("unknown", "test").await;
710 assert!(result.is_err());
711 assert!(result.unwrap_err().contains("Adapter not found"));
712 }
713
714 #[tokio::test]
715 async fn test_enabled_protocols_empty() {
716 let router = Router::new();
717 let protocols = router.enabled_protocols();
718 assert_eq!(protocols.len(), 0);
719 }
720
721 #[tokio::test]
722 async fn test_enabled_protocols_multiple() {
723 let mut router = Router::new();
724 router.add_adapter(Box::new(RestAdapter::new()));
725 router.add_adapter(Box::new(GraphQLAdapter::new()));
726 router.add_adapter(Box::new(GrpcAdapter::new()));
727
728 let protocols = router.enabled_protocols();
729 assert_eq!(protocols.len(), 3);
730 assert!(protocols.contains(&"rest".to_string()));
731 assert!(protocols.contains(&"graphql".to_string()));
732 assert!(protocols.contains(&"grpc".to_string()));
733 }
734
735 #[tokio::test]
736 async fn test_can_handle_rest() {
737 let mut router = Router::new();
738 assert!(!router.can_handle_rest("test"));
739
740 router.add_adapter(Box::new(RestAdapter::new()));
741 assert!(router.can_handle_rest("test"));
742 }
743
744 #[tokio::test]
745 async fn test_can_handle_graphql() {
746 let mut router = Router::new();
747 assert!(!router.can_handle_graphql("test"));
748
749 router.add_adapter(Box::new(GraphQLAdapter::new()));
750 assert!(router.can_handle_graphql("test"));
751 }
752
753 #[tokio::test]
754 async fn test_can_handle_grpc() {
755 let mut router = Router::new();
756 assert!(!router.can_handle_grpc("test"));
757
758 router.add_adapter(Box::new(GrpcAdapter::new()));
759 assert!(router.can_handle_grpc("test"));
760 }
761
762 #[tokio::test]
765 async fn test_integration_single_handler_rest() {
766 let mut router = Router::new();
768 router.register("get_user", || async { "User data".to_string() });
769
770 let mut rest = RestAdapter::new();
772 rest.route("GET", "/users/:id", "get_user");
773 router.add_adapter(Box::new(rest));
774
775 let response = router.route_request("rest", "GET /users/42").await;
777 assert!(response.is_ok());
778 assert!(response.unwrap().contains("get_user"));
779 }
780
781 #[tokio::test]
782 async fn test_integration_single_handler_graphql() {
783 let mut router = Router::new();
785 router.register("get_user", || async { "User data".to_string() });
786
787 let mut graphql = GraphQLAdapter::new();
789 graphql.query("user", "get_user");
790 router.add_adapter(Box::new(graphql));
791
792 let response = router.route_request("graphql", "query { user }").await;
794 assert!(response.is_ok());
795 assert!(response.unwrap().contains("get_user"));
796 }
797
798 #[tokio::test]
799 async fn test_integration_single_handler_grpc() {
800 let mut router = Router::new();
802 router.register("get_user", || async { "User data".to_string() });
803
804 let mut grpc = GrpcAdapter::new();
806 grpc.unary("UserService", "GetUser", "get_user");
807 router.add_adapter(Box::new(grpc));
808
809 let response = router
811 .route_request("grpc", "UserService.GetUser:{\"id\":42}")
812 .await;
813 assert!(response.is_ok());
814 assert!(response.unwrap().contains("get_user"));
815 }
816
817 #[tokio::test]
818 async fn test_integration_single_handler_all_protocols() {
819 let mut router = Router::new();
821 router.register("get_user", || async { "User data".to_string() });
822
823 let mut rest = RestAdapter::new();
825 rest.route("GET", "/users/:id", "get_user");
826 router.add_adapter(Box::new(rest));
827
828 let mut graphql = GraphQLAdapter::new();
830 graphql.query("user", "get_user");
831 router.add_adapter(Box::new(graphql));
832
833 let mut grpc = GrpcAdapter::new();
835 grpc.unary("UserService", "GetUser", "get_user");
836 router.add_adapter(Box::new(grpc));
837
838 let rest_response = router.route_request("rest", "GET /users/42").await;
840 assert!(rest_response.is_ok());
841 assert!(rest_response.unwrap().contains("get_user"));
842
843 let graphql_response = router.route_request("graphql", "query { user }").await;
845 assert!(graphql_response.is_ok());
846 assert!(graphql_response.unwrap().contains("get_user"));
847
848 let grpc_response = router
850 .route_request("grpc", "UserService.GetUser:{\"id\":42}")
851 .await;
852 assert!(grpc_response.is_ok());
853 assert!(grpc_response.unwrap().contains("get_user"));
854 }
855
856 #[tokio::test]
857 async fn test_integration_multiple_handlers_all_protocols() {
858 let mut router = Router::new();
860 router.register("get_user", || async { "User data".to_string() });
861 router.register("list_users", || async { "Users list".to_string() });
862 router.register("create_user", || async { "Created user".to_string() });
863
864 let mut rest = RestAdapter::new();
866 rest.route("GET", "/users/:id", "get_user");
867 rest.route("GET", "/users", "list_users");
868 rest.route("POST", "/users", "create_user");
869 router.add_adapter(Box::new(rest));
870
871 let mut graphql = GraphQLAdapter::new();
873 graphql.query("user", "get_user");
874 graphql.query("users", "list_users");
875 graphql.mutation("createUser", "create_user");
876 router.add_adapter(Box::new(graphql));
877
878 let mut grpc = GrpcAdapter::new();
880 grpc.unary("UserService", "GetUser", "get_user");
881 grpc.unary("UserService", "ListUsers", "list_users");
882 grpc.unary("UserService", "CreateUser", "create_user");
883 router.add_adapter(Box::new(grpc));
884
885 assert!(router
887 .route_request("rest", "GET /users/42")
888 .await
889 .unwrap()
890 .contains("get_user"));
891 assert!(router
892 .route_request("graphql", "query { user }")
893 .await
894 .unwrap()
895 .contains("get_user"));
896 assert!(router
897 .route_request("grpc", "UserService.GetUser:{}")
898 .await
899 .unwrap()
900 .contains("get_user"));
901 }
902
903 #[tokio::test]
904 async fn test_integration_error_handling_rest_404() {
905 let mut router = Router::new();
907
908 let mut rest = RestAdapter::new();
909 rest.route("GET", "/users/:id", "get_user");
910 router.add_adapter(Box::new(rest));
911
912 let response = router.route_request("rest", "GET /posts/42").await;
913 assert!(response.is_ok());
914 assert!(response.unwrap().contains("HTTP 404"));
915 }
916
917 #[tokio::test]
918 async fn test_integration_error_handling_graphql_not_found() {
919 let mut router = Router::new();
921
922 let mut graphql = GraphQLAdapter::new();
923 graphql.query("user", "get_user");
924 router.add_adapter(Box::new(graphql));
925
926 let response = router.route_request("graphql", "query { post }").await;
927 assert!(response.is_ok());
928 assert!(response.unwrap().contains("errors"));
929 }
930
931 #[tokio::test]
932 async fn test_integration_error_handling_grpc_unimplemented() {
933 let mut router = Router::new();
935
936 let mut grpc = GrpcAdapter::new();
937 grpc.unary("UserService", "GetUser", "get_user");
938 router.add_adapter(Box::new(grpc));
939
940 let response = router.route_request("grpc", "UserService.GetPost:{}").await;
941 assert!(response.is_ok());
942 assert!(response.unwrap().contains("grpc-status: 12")); }
944
945 #[tokio::test]
946 async fn test_integration_unknown_protocol() {
947 let router = Router::new();
949
950 let response = router.route_request("unknown", "request").await;
951 assert!(response.is_err());
952 assert!(response.unwrap_err().contains("Adapter not found"));
953 }
954
955 #[tokio::test]
956 async fn test_integration_protocol_specific_features_rest_methods() {
957 let mut router = Router::new();
959 router.register("get_users", || async { "Users".to_string() });
960 router.register("create_user", || async { "Created".to_string() });
961 router.register("update_user", || async { "Updated".to_string() });
962 router.register("delete_user", || async { "Deleted".to_string() });
963
964 let mut rest = RestAdapter::new();
965 rest.route("GET", "/users", "get_users");
966 rest.route("POST", "/users", "create_user");
967 rest.route("PUT", "/users/:id", "update_user");
968 rest.route("DELETE", "/users/:id", "delete_user");
969 router.add_adapter(Box::new(rest));
970
971 assert!(router
973 .route_request("rest", "GET /users")
974 .await
975 .unwrap()
976 .contains("get_users"));
977 assert!(router
978 .route_request("rest", "POST /users")
979 .await
980 .unwrap()
981 .contains("create_user"));
982 assert!(router
983 .route_request("rest", "PUT /users/42")
984 .await
985 .unwrap()
986 .contains("update_user"));
987 assert!(router
988 .route_request("rest", "DELETE /users/42")
989 .await
990 .unwrap()
991 .contains("delete_user"));
992 }
993
994 #[tokio::test]
995 async fn test_integration_protocol_specific_features_graphql_types() {
996 let mut router = Router::new();
998 router.register("get_user", || async { "User".to_string() });
999 router.register("create_user", || async { "Created".to_string() });
1000
1001 let mut graphql = GraphQLAdapter::new();
1002 graphql.query("user", "get_user");
1003 graphql.mutation("createUser", "create_user");
1004 router.add_adapter(Box::new(graphql));
1005
1006 assert!(router
1008 .route_request("graphql", "query { user }")
1009 .await
1010 .unwrap()
1011 .contains("get_user"));
1012
1013 assert!(router
1015 .route_request("graphql", "mutation { createUser }")
1016 .await
1017 .unwrap()
1018 .contains("create_user"));
1019 }
1020
1021 #[tokio::test]
1022 async fn test_integration_protocol_specific_features_grpc_streaming() {
1023 let mut router = Router::new();
1025 router.register("get_user", || async { "User".to_string() });
1026 router.register("list_users", || async { "Users".to_string() });
1027
1028 let mut grpc = GrpcAdapter::new();
1029 grpc.unary("UserService", "GetUser", "get_user");
1030 grpc.server_streaming("UserService", "ListUsers", "list_users");
1031 router.add_adapter(Box::new(grpc));
1032
1033 let unary_response = router
1035 .route_request("grpc", "UserService.GetUser:{}")
1036 .await
1037 .unwrap();
1038 assert!(unary_response.contains("unary"));
1039
1040 let streaming_response = router
1042 .route_request("grpc", "UserService.ListUsers:{}")
1043 .await
1044 .unwrap();
1045 assert!(streaming_response.contains("server_streaming"));
1046 }
1047}