1use std::{collections::HashMap, future::Future};
65
66pub mod adapter;
67pub mod builder;
68#[cfg(feature = "router")]
69pub mod config;
70pub mod contract;
71pub mod docs;
72pub mod graphiql;
73pub mod graphql;
74pub mod grpc;
75pub mod grpc_explorer;
76pub mod handler;
77pub mod metadata;
78pub mod method;
79pub mod openapi;
80pub mod rest;
81pub mod scalar;
82pub mod schema;
83
84#[cfg(feature = "router-graphql")]
86pub mod graphql_prod;
87#[cfg(feature = "router-grpc")]
88pub mod grpc_prod;
89
90pub use adapter::ProtocolAdapter;
91pub use builder::RouteBuilder;
92#[cfg(feature = "router")]
93pub use config::{GraphQLConfig, GrpcConfig, RestConfig, RouterConfig, ServerConfig};
94pub use contract::{
95 ContractTestConfig, ContractTestResult, ContractTestResults, ContractTestable, ContractTester,
96};
97pub use docs::DocsConfig;
98pub use graphiql::{graphiql_html, GraphiQLConfig, GraphiQLTheme};
99pub use graphql::{GraphQLAdapter, GraphQLOperation, OperationType};
100#[cfg(feature = "router-graphql")]
102pub use graphql_prod::GraphQLProductionAdapter;
103pub use grpc::{GrpcAdapter, GrpcMethod, GrpcMethodType, GrpcRequest, GrpcStatus};
104pub use grpc_explorer::{grpc_explorer_html, GrpcExplorerConfig, GrpcExplorerTheme};
105#[cfg(feature = "router-grpc")]
106pub use grpc_prod::{protobuf, status, streaming, GrpcProductionAdapter, GrpcService};
107pub use handler::{Handler, HandlerFn};
108pub use metadata::RouteMetadata;
109pub use method::Method;
110pub use openapi::{OpenApiGenerator, OpenApiServer};
111pub use rest::{RestAdapter, RestRequest, RestResponse, RestRoute};
112pub use scalar::{scalar_html, ScalarConfig, ScalarLayout, ScalarTheme};
113pub use schema::ToJsonSchema;
114
115pub struct Router {
120 handlers: HashMap<String, Box<dyn Handler>>,
121 adapters: HashMap<String, Box<dyn ProtocolAdapter>>,
122 routes: Vec<RouteMetadata>,
123 #[cfg(feature = "router")]
124 #[allow(dead_code)]
125 config: Option<RouterConfig>,
126}
127
128impl Router {
129 pub fn new() -> Self {
131 Self {
132 handlers: HashMap::new(),
133 adapters: HashMap::new(),
134 routes: Vec::new(),
135 #[cfg(feature = "router")]
136 config: None,
137 }
138 }
139
140 #[cfg(feature = "router")]
142 pub fn with_config(config: RouterConfig) -> Self {
143 let mut router = Self {
144 handlers: HashMap::new(),
145 adapters: HashMap::new(),
146 routes: Vec::new(),
147 config: Some(config.clone()),
148 };
149
150 if config.has_protocol("rest") {
152 router.add_adapter(Box::new(RestAdapter::new()));
153 }
154 if config.has_protocol("graphql") {
155 router.add_adapter(Box::new(GraphQLAdapter::new()));
156 }
157 if config.has_protocol("grpc") {
158 router.add_adapter(Box::new(GrpcAdapter::new()));
159 }
160
161 router
162 }
163
164 pub fn register<F, Fut>(&mut self, name: &str, handler: F)
166 where
167 F: Fn() -> Fut + Send + Sync + 'static,
168 Fut: Future<Output = String> + Send + 'static,
169 {
170 self.handlers
171 .insert(name.to_string(), Box::new(HandlerFn::new(handler)));
172 }
173
174 pub fn handlers_count(&self) -> usize {
176 self.handlers.len()
177 }
178
179 pub fn add_adapter(&mut self, adapter: Box<dyn ProtocolAdapter>) {
181 self.adapters.insert(adapter.name().to_string(), adapter);
182 }
183
184 pub fn has_adapter(&self, name: &str) -> bool {
186 self.adapters.contains_key(name)
187 }
188
189 pub fn get_adapter(&self, name: &str) -> Option<&dyn ProtocolAdapter> {
191 self.adapters.get(name).map(|b| &**b)
192 }
193
194 pub async fn route_request(&self, protocol: &str, request: &str) -> Result<String, String> {
196 let adapter = self
197 .get_adapter(protocol)
198 .ok_or_else(|| format!("Adapter not found: {}", protocol))?;
199
200 adapter.handle(request).await
201 }
202
203 pub async fn execute(&self, name: &str) -> Result<String, String> {
205 match self.handlers.get(name) {
206 Some(handler) => handler.call().await,
207 None => Err(format!("Handler '{}' not found", name)),
208 }
209 }
210
211 pub fn list_handlers(&self) -> Vec<String> {
216 self.handlers.keys().cloned().collect()
217 }
218
219 pub async fn call_handler(&self, name: &str, _request: &str) -> Result<String, String> {
224 self.execute(name).await
227 }
228
229 pub fn can_handle_rest(&self, _name: &str) -> bool {
231 self.has_adapter("rest")
232 }
233
234 pub fn can_handle_graphql(&self, _name: &str) -> bool {
236 self.has_adapter("graphql")
237 }
238
239 pub fn can_handle_grpc(&self, _name: &str) -> bool {
241 self.has_adapter("grpc")
242 }
243
244 pub fn enabled_protocols(&self) -> Vec<String> {
246 self.adapters.keys().cloned().collect()
247 }
248
249 pub fn add_route(&mut self, metadata: RouteMetadata) {
254 self.routes.push(metadata);
255 }
256
257 pub fn routes(&self) -> &[RouteMetadata] {
262 &self.routes
263 }
264
265 pub fn get<F, Fut>(&mut self, path: &str, handler: F)
271 where
272 F: Fn() -> Fut + Send + Sync + 'static,
273 Fut: Future<Output = String> + Send + 'static,
274 {
275 let handler_name = format!("GET:{}", path);
276 self.register(&handler_name, handler);
277 self.add_route(RouteMetadata::new(path, Method::GET, "rest"));
278 }
279
280 pub fn post<F, Fut>(&mut self, path: &str, handler: F)
286 where
287 F: Fn() -> Fut + Send + Sync + 'static,
288 Fut: Future<Output = String> + Send + 'static,
289 {
290 let handler_name = format!("POST:{}", path);
291 self.register(&handler_name, handler);
292 self.add_route(RouteMetadata::new(path, Method::POST, "rest"));
293 }
294
295 pub fn put<F, Fut>(&mut self, path: &str, handler: F)
301 where
302 F: Fn() -> Fut + Send + Sync + 'static,
303 Fut: Future<Output = String> + Send + 'static,
304 {
305 let handler_name = format!("PUT:{}", path);
306 self.register(&handler_name, handler);
307 self.add_route(RouteMetadata::new(path, Method::PUT, "rest"));
308 }
309
310 pub fn delete<F, Fut>(&mut self, path: &str, handler: F)
316 where
317 F: Fn() -> Fut + Send + Sync + 'static,
318 Fut: Future<Output = String> + Send + 'static,
319 {
320 let handler_name = format!("DELETE:{}", path);
321 self.register(&handler_name, handler);
322 self.add_route(RouteMetadata::new(path, Method::DELETE, "rest"));
323 }
324
325 pub fn patch<F, Fut>(&mut self, path: &str, handler: F)
331 where
332 F: Fn() -> Fut + Send + Sync + 'static,
333 Fut: Future<Output = String> + Send + 'static,
334 {
335 let handler_name = format!("PATCH:{}", path);
336 self.register(&handler_name, handler);
337 self.add_route(RouteMetadata::new(path, Method::PATCH, "rest"));
338 }
339
340 pub fn head<F, Fut>(&mut self, path: &str, handler: F)
346 where
347 F: Fn() -> Fut + Send + Sync + 'static,
348 Fut: Future<Output = String> + Send + 'static,
349 {
350 let handler_name = format!("HEAD:{}", path);
351 self.register(&handler_name, handler);
352 self.add_route(RouteMetadata::new(path, Method::HEAD, "rest"));
353 }
354
355 pub fn options<F, Fut>(&mut self, path: &str, handler: F)
361 where
362 F: Fn() -> Fut + Send + Sync + 'static,
363 Fut: Future<Output = String> + Send + 'static,
364 {
365 let handler_name = format!("OPTIONS:{}", path);
366 self.register(&handler_name, handler);
367 self.add_route(RouteMetadata::new(path, Method::OPTIONS, "rest"));
368 }
369
370 pub async fn call_rest(&self, method: &str, path: &str) -> Result<String, String> {
372 let adapter = self
373 .adapters
374 .get("rest")
375 .ok_or_else(|| "REST adapter not enabled".to_string())?;
376
377 let request = format!("{} {}", method, path);
378 adapter.handle(&request).await
379 }
380
381 pub async fn call_graphql(&self, query: &str) -> Result<String, String> {
383 let adapter = self
384 .adapters
385 .get("graphql")
386 .ok_or_else(|| "GraphQL adapter not enabled".to_string())?;
387
388 adapter.handle(query).await
389 }
390
391 pub async fn call_grpc(&self, method: &str, request: &str) -> Result<String, String> {
393 let adapter = self
394 .adapters
395 .get("grpc")
396 .ok_or_else(|| "gRPC adapter not enabled".to_string())?;
397
398 let grpc_request = format!("{}:{}", method, request);
399 adapter.handle(&grpc_request).await
400 }
401
402 pub fn scalar(&self, title: &str, version: &str) -> String {
424 let config = scalar::ScalarConfig::default();
425 self.scalar_docs(config, title, version)
426 }
427
428 pub fn scalar_docs(&self, config: scalar::ScalarConfig, title: &str, version: &str) -> String {
454 let spec = OpenApiGenerator::new(title, version).generate(self);
456 let spec_json = serde_json::to_string(&spec).unwrap_or_else(|_| "{}".to_string());
457
458 scalar::scalar_html(&config, title, &spec_json)
460 }
461}
462
463impl Default for Router {
464 fn default() -> Self {
465 Self::new()
466 }
467}
468
469#[cfg(test)]
470mod tests {
471 use super::*;
472
473 #[tokio::test]
474 async fn test_router_creation() {
475 let router = Router::new();
476 assert_eq!(router.handlers_count(), 0);
477 }
478
479 #[tokio::test]
480 async fn test_handler_registration() {
481 let mut router = Router::new();
482 router.register("test", || async { "Hello".to_string() });
483 assert_eq!(router.handlers_count(), 1);
484 }
485
486 #[tokio::test]
487 async fn test_handler_execution() {
488 let mut router = Router::new();
489 router.register("test", || async { "Hello".to_string() });
490 let result = router.execute("test").await;
491 assert_eq!(result, Ok("Hello".to_string()));
492 }
493
494 #[tokio::test]
496 async fn test_router_starts_with_no_routes() {
497 let router = Router::new();
498 let routes = router.routes();
499 assert_eq!(routes.len(), 0);
500 }
501
502 #[tokio::test]
503 async fn test_add_route_metadata() {
504 let mut router = Router::new();
505 let metadata = RouteMetadata::new("/users", "GET", "rest");
506
507 router.add_route(metadata.clone());
508
509 let routes = router.routes();
510 assert_eq!(routes.len(), 1);
511 assert_eq!(routes[0].path, "/users");
512 assert_eq!(routes[0].method, "GET");
513 assert_eq!(routes[0].protocol, "rest");
514 }
515
516 #[tokio::test]
517 async fn test_add_multiple_routes() {
518 let mut router = Router::new();
519
520 router.add_route(RouteMetadata::new("/users", "GET", "rest"));
521 router.add_route(RouteMetadata::new("/users", "POST", "rest"));
522 router.add_route(RouteMetadata::new("/posts", "GET", "rest"));
523
524 let routes = router.routes();
525 assert_eq!(routes.len(), 3);
526 }
527
528 #[tokio::test]
529 async fn test_routes_with_different_protocols() {
530 let mut router = Router::new();
531
532 router.add_route(RouteMetadata::new("/users", "GET", "rest"));
533 router.add_route(RouteMetadata::new("users", "query", "graphql"));
534 router.add_route(RouteMetadata::new("UserService.GetUser", "unary", "grpc"));
535
536 let routes = router.routes();
537 assert_eq!(routes.len(), 3);
538
539 assert_eq!(routes[0].protocol, "rest");
540 assert_eq!(routes[1].protocol, "graphql");
541 assert_eq!(routes[2].protocol, "grpc");
542 }
543
544 #[tokio::test]
545 async fn test_routes_returns_immutable_reference() {
546 let mut router = Router::new();
547 router.add_route(RouteMetadata::new("/test", "GET", "rest"));
548
549 let routes1 = router.routes();
550 let routes2 = router.routes();
551
552 assert_eq!(routes1.len(), routes2.len());
554 assert_eq!(routes1[0].path, routes2[0].path);
555 }
556
557 #[tokio::test]
559 async fn test_route_get_method() {
560 let mut router = Router::new();
561 router.get("/users", || async { "User list".to_string() });
562
563 let routes = router.routes();
564 assert_eq!(routes.len(), 1);
565 assert_eq!(routes[0].path, "/users");
566 assert_eq!(routes[0].method, "GET");
567 assert_eq!(routes[0].protocol, "rest");
568 }
569
570 #[tokio::test]
571 async fn test_route_post_method() {
572 let mut router = Router::new();
573 router.post("/users", || async { "User created".to_string() });
574
575 let routes = router.routes();
576 assert_eq!(routes.len(), 1);
577 assert_eq!(routes[0].path, "/users");
578 assert_eq!(routes[0].method, "POST");
579 assert_eq!(routes[0].protocol, "rest");
580 }
581
582 #[tokio::test]
583 async fn test_route_put_method() {
584 let mut router = Router::new();
585 router.put("/users/1", || async { "User updated".to_string() });
586
587 let routes = router.routes();
588 assert_eq!(routes.len(), 1);
589 assert_eq!(routes[0].method, "PUT");
590 }
591
592 #[tokio::test]
593 async fn test_route_delete_method() {
594 let mut router = Router::new();
595 router.delete("/users/1", || async { "User deleted".to_string() });
596
597 let routes = router.routes();
598 assert_eq!(routes.len(), 1);
599 assert_eq!(routes[0].method, "DELETE");
600 }
601
602 #[tokio::test]
603 async fn test_route_patch_method() {
604 let mut router = Router::new();
605 router.patch("/users/1", || async { "User patched".to_string() });
606
607 let routes = router.routes();
608 assert_eq!(routes.len(), 1);
609 assert_eq!(routes[0].method, "PATCH");
610 }
611
612 #[tokio::test]
613 async fn test_multiple_routes_different_methods() {
614 let mut router = Router::new();
615 router.get("/users", || async { "List".to_string() });
616 router.post("/users", || async { "Create".to_string() });
617 router.put("/users/1", || async { "Update".to_string() });
618 router.delete("/users/1", || async { "Delete".to_string() });
619
620 let routes = router.routes();
621 assert_eq!(routes.len(), 4);
622
623 assert_eq!(routes[0].method, "GET");
624 assert_eq!(routes[1].method, "POST");
625 assert_eq!(routes[2].method, "PUT");
626 assert_eq!(routes[3].method, "DELETE");
627 }
628
629 #[tokio::test]
630 async fn test_route_method_with_path_params() {
631 let mut router = Router::new();
632 router.get("/users/{id}", || async { "User details".to_string() });
633 router.get("/users/{id}/posts/{post_id}", || async {
634 "Post details".to_string()
635 });
636
637 let routes = router.routes();
638 assert_eq!(routes.len(), 2);
639 assert_eq!(routes[0].path, "/users/{id}");
640 assert_eq!(routes[1].path, "/users/{id}/posts/{post_id}");
641 }
642
643 #[tokio::test]
644 async fn test_route_registration_and_execution() {
645 let mut router = Router::new();
646 router.get("/test", || async { "GET response".to_string() });
647 router.post("/test", || async { "POST response".to_string() });
648
649 assert_eq!(router.routes().len(), 2);
651 assert_eq!(router.handlers_count(), 2);
652
653 let result1 = router.execute("GET:/test").await;
655 let result2 = router.execute("POST:/test").await;
656
657 assert_eq!(result1, Ok("GET response".to_string()));
658 assert_eq!(result2, Ok("POST response".to_string()));
659 }
660
661 #[tokio::test]
663 async fn test_scalar_generates_html() {
664 let mut router = Router::new();
665 router.get("/users", || async { "Users".to_string() });
666
667 let html = router.scalar("Test API", "1.0.0");
668
669 assert!(html.contains("<!DOCTYPE html>"));
670 assert!(html.contains("<title>Test API - API Documentation</title>"));
671 assert!(html.contains("@scalar/api-reference"));
672 }
673
674 #[tokio::test]
675 async fn test_scalar_contains_openapi_spec() {
676 let mut router = Router::new();
677 router.get("/users", || async { "Users".to_string() });
678 router.post("/users", || async { "User created".to_string() });
679
680 let html = router.scalar("Test API", "1.0.0");
681
682 assert!(html.contains("openapi"));
684 assert!(html.contains("Test API"));
685 assert!(html.contains("1.0.0"));
686 }
687
688 #[tokio::test]
689 async fn test_scalar_docs_with_custom_config() {
690 let mut router = Router::new();
691 router.get("/users", || async { "Users".to_string() });
692
693 let config = scalar::ScalarConfig::new()
694 .theme(scalar::ScalarTheme::Light)
695 .show_sidebar(false);
696
697 let html = router.scalar_docs(config, "Custom API", "2.0.0");
698
699 assert!(html.contains("Custom API"));
700 assert!(html.contains(r#""theme":"light""#));
701 assert!(html.contains(r#""showSidebar":false"#));
702 }
703
704 #[tokio::test]
705 async fn test_scalar_docs_with_custom_css() {
706 let mut router = Router::new();
707 router.get("/test", || async { "Test".to_string() });
708
709 let config = scalar::ScalarConfig::new().custom_css("body { font-family: 'Inter'; }");
710
711 let html = router.scalar_docs(config, "API", "1.0");
712
713 assert!(html.contains("<style>body { font-family: 'Inter'; }</style>"));
714 }
715
716 #[tokio::test]
717 async fn test_scalar_with_multiple_routes() {
718 let mut router = Router::new();
719 router.get("/users", || async { "Users".to_string() });
720 router.post("/users", || async { "Create".to_string() });
721 router.get("/users/{id}", || async { "User details".to_string() });
722 router.delete("/users/{id}", || async { "Delete".to_string() });
723
724 let html = router.scalar("API", "1.0.0");
725
726 assert!(html.contains("/users"));
728 }
729
730 #[tokio::test]
732 async fn test_get_adapter_returns_adapter() {
733 let mut router = Router::new();
734 router.add_adapter(Box::new(RestAdapter::new()));
735
736 let adapter = router.get_adapter("rest");
737 assert!(adapter.is_some());
738 assert_eq!(adapter.unwrap().name(), "rest");
739 }
740
741 #[tokio::test]
742 async fn test_get_adapter_returns_none_for_missing() {
743 let router = Router::new();
744 let adapter = router.get_adapter("rest");
745 assert!(adapter.is_none());
746 }
747
748 #[tokio::test]
749 async fn test_route_request_success() {
750 let mut router = Router::new();
751 router.register("test_handler", || async { "Success!".to_string() });
752
753 let mut rest_adapter = RestAdapter::new();
755 rest_adapter.route("GET", "/test", "test_handler");
756 router.add_adapter(Box::new(rest_adapter));
757
758 let result = router.route_request("rest", "GET /test").await;
759 assert!(result.is_ok());
760 let response = result.unwrap();
761 assert!(response.contains("HTTP 200") || response.contains("test_handler"));
762 }
763
764 #[tokio::test]
765 async fn test_route_request_unknown_adapter() {
766 let router = Router::new();
767 let result = router.route_request("unknown", "test").await;
768 assert!(result.is_err());
769 assert!(result.unwrap_err().contains("Adapter not found"));
770 }
771
772 #[tokio::test]
773 async fn test_enabled_protocols_empty() {
774 let router = Router::new();
775 let protocols = router.enabled_protocols();
776 assert_eq!(protocols.len(), 0);
777 }
778
779 #[tokio::test]
780 async fn test_enabled_protocols_multiple() {
781 let mut router = Router::new();
782 router.add_adapter(Box::new(RestAdapter::new()));
783 router.add_adapter(Box::new(GraphQLAdapter::new()));
784 router.add_adapter(Box::new(GrpcAdapter::new()));
785
786 let protocols = router.enabled_protocols();
787 assert_eq!(protocols.len(), 3);
788 assert!(protocols.contains(&"rest".to_string()));
789 assert!(protocols.contains(&"graphql".to_string()));
790 assert!(protocols.contains(&"grpc".to_string()));
791 }
792
793 #[tokio::test]
794 async fn test_can_handle_rest() {
795 let mut router = Router::new();
796 assert!(!router.can_handle_rest("test"));
797
798 router.add_adapter(Box::new(RestAdapter::new()));
799 assert!(router.can_handle_rest("test"));
800 }
801
802 #[tokio::test]
803 async fn test_can_handle_graphql() {
804 let mut router = Router::new();
805 assert!(!router.can_handle_graphql("test"));
806
807 router.add_adapter(Box::new(GraphQLAdapter::new()));
808 assert!(router.can_handle_graphql("test"));
809 }
810
811 #[tokio::test]
812 async fn test_can_handle_grpc() {
813 let mut router = Router::new();
814 assert!(!router.can_handle_grpc("test"));
815
816 router.add_adapter(Box::new(GrpcAdapter::new()));
817 assert!(router.can_handle_grpc("test"));
818 }
819
820 #[tokio::test]
823 async fn test_integration_single_handler_rest() {
824 let mut router = Router::new();
826 router.register("get_user", || async { "User data".to_string() });
827
828 let mut rest = RestAdapter::new();
830 rest.route("GET", "/users/:id", "get_user");
831 router.add_adapter(Box::new(rest));
832
833 let response = router.route_request("rest", "GET /users/42").await;
835 assert!(response.is_ok());
836 assert!(response.unwrap().contains("get_user"));
837 }
838
839 #[tokio::test]
840 async fn test_integration_single_handler_graphql() {
841 let mut router = Router::new();
843 router.register("get_user", || async { "User data".to_string() });
844
845 let mut graphql = GraphQLAdapter::new();
847 graphql.query("user", "get_user");
848 router.add_adapter(Box::new(graphql));
849
850 let response = router.route_request("graphql", "query { user }").await;
852 assert!(response.is_ok());
853 assert!(response.unwrap().contains("get_user"));
854 }
855
856 #[tokio::test]
857 async fn test_integration_single_handler_grpc() {
858 let mut router = Router::new();
860 router.register("get_user", || async { "User data".to_string() });
861
862 let mut grpc = GrpcAdapter::new();
864 grpc.unary("UserService", "GetUser", "get_user");
865 router.add_adapter(Box::new(grpc));
866
867 let response = router
869 .route_request("grpc", "UserService.GetUser:{\"id\":42}")
870 .await;
871 assert!(response.is_ok());
872 assert!(response.unwrap().contains("get_user"));
873 }
874
875 #[tokio::test]
876 async fn test_integration_single_handler_all_protocols() {
877 let mut router = Router::new();
879 router.register("get_user", || async { "User data".to_string() });
880
881 let mut rest = RestAdapter::new();
883 rest.route("GET", "/users/:id", "get_user");
884 router.add_adapter(Box::new(rest));
885
886 let mut graphql = GraphQLAdapter::new();
888 graphql.query("user", "get_user");
889 router.add_adapter(Box::new(graphql));
890
891 let mut grpc = GrpcAdapter::new();
893 grpc.unary("UserService", "GetUser", "get_user");
894 router.add_adapter(Box::new(grpc));
895
896 let rest_response = router.route_request("rest", "GET /users/42").await;
898 assert!(rest_response.is_ok());
899 assert!(rest_response.unwrap().contains("get_user"));
900
901 let graphql_response = router.route_request("graphql", "query { user }").await;
903 assert!(graphql_response.is_ok());
904 assert!(graphql_response.unwrap().contains("get_user"));
905
906 let grpc_response = router
908 .route_request("grpc", "UserService.GetUser:{\"id\":42}")
909 .await;
910 assert!(grpc_response.is_ok());
911 assert!(grpc_response.unwrap().contains("get_user"));
912 }
913
914 #[tokio::test]
915 async fn test_integration_multiple_handlers_all_protocols() {
916 let mut router = Router::new();
918 router.register("get_user", || async { "User data".to_string() });
919 router.register("list_users", || async { "Users list".to_string() });
920 router.register("create_user", || async { "Created user".to_string() });
921
922 let mut rest = RestAdapter::new();
924 rest.route("GET", "/users/:id", "get_user");
925 rest.route("GET", "/users", "list_users");
926 rest.route("POST", "/users", "create_user");
927 router.add_adapter(Box::new(rest));
928
929 let mut graphql = GraphQLAdapter::new();
931 graphql.query("user", "get_user");
932 graphql.query("users", "list_users");
933 graphql.mutation("createUser", "create_user");
934 router.add_adapter(Box::new(graphql));
935
936 let mut grpc = GrpcAdapter::new();
938 grpc.unary("UserService", "GetUser", "get_user");
939 grpc.unary("UserService", "ListUsers", "list_users");
940 grpc.unary("UserService", "CreateUser", "create_user");
941 router.add_adapter(Box::new(grpc));
942
943 assert!(router
945 .route_request("rest", "GET /users/42")
946 .await
947 .unwrap()
948 .contains("get_user"));
949 assert!(router
950 .route_request("graphql", "query { user }")
951 .await
952 .unwrap()
953 .contains("get_user"));
954 assert!(router
955 .route_request("grpc", "UserService.GetUser:{}")
956 .await
957 .unwrap()
958 .contains("get_user"));
959 }
960
961 #[tokio::test]
962 async fn test_integration_error_handling_rest_404() {
963 let mut router = Router::new();
965
966 let mut rest = RestAdapter::new();
967 rest.route("GET", "/users/:id", "get_user");
968 router.add_adapter(Box::new(rest));
969
970 let response = router.route_request("rest", "GET /posts/42").await;
971 assert!(response.is_ok());
972 assert!(response.unwrap().contains("HTTP 404"));
973 }
974
975 #[tokio::test]
976 async fn test_integration_error_handling_graphql_not_found() {
977 let mut router = Router::new();
979
980 let mut graphql = GraphQLAdapter::new();
981 graphql.query("user", "get_user");
982 router.add_adapter(Box::new(graphql));
983
984 let response = router.route_request("graphql", "query { post }").await;
985 assert!(response.is_ok());
986 assert!(response.unwrap().contains("errors"));
987 }
988
989 #[tokio::test]
990 async fn test_integration_error_handling_grpc_unimplemented() {
991 let mut router = Router::new();
993
994 let mut grpc = GrpcAdapter::new();
995 grpc.unary("UserService", "GetUser", "get_user");
996 router.add_adapter(Box::new(grpc));
997
998 let response = router.route_request("grpc", "UserService.GetPost:{}").await;
999 assert!(response.is_ok());
1000 assert!(response.unwrap().contains("grpc-status: 12")); }
1002
1003 #[tokio::test]
1004 async fn test_integration_unknown_protocol() {
1005 let router = Router::new();
1007
1008 let response = router.route_request("unknown", "request").await;
1009 assert!(response.is_err());
1010 assert!(response.unwrap_err().contains("Adapter not found"));
1011 }
1012
1013 #[tokio::test]
1014 async fn test_integration_protocol_specific_features_rest_methods() {
1015 let mut router = Router::new();
1017 router.register("get_users", || async { "Users".to_string() });
1018 router.register("create_user", || async { "Created".to_string() });
1019 router.register("update_user", || async { "Updated".to_string() });
1020 router.register("delete_user", || async { "Deleted".to_string() });
1021
1022 let mut rest = RestAdapter::new();
1023 rest.route("GET", "/users", "get_users");
1024 rest.route("POST", "/users", "create_user");
1025 rest.route("PUT", "/users/:id", "update_user");
1026 rest.route("DELETE", "/users/:id", "delete_user");
1027 router.add_adapter(Box::new(rest));
1028
1029 assert!(router
1031 .route_request("rest", "GET /users")
1032 .await
1033 .unwrap()
1034 .contains("get_users"));
1035 assert!(router
1036 .route_request("rest", "POST /users")
1037 .await
1038 .unwrap()
1039 .contains("create_user"));
1040 assert!(router
1041 .route_request("rest", "PUT /users/42")
1042 .await
1043 .unwrap()
1044 .contains("update_user"));
1045 assert!(router
1046 .route_request("rest", "DELETE /users/42")
1047 .await
1048 .unwrap()
1049 .contains("delete_user"));
1050 }
1051
1052 #[tokio::test]
1053 async fn test_integration_protocol_specific_features_graphql_types() {
1054 let mut router = Router::new();
1056 router.register("get_user", || async { "User".to_string() });
1057 router.register("create_user", || async { "Created".to_string() });
1058
1059 let mut graphql = GraphQLAdapter::new();
1060 graphql.query("user", "get_user");
1061 graphql.mutation("createUser", "create_user");
1062 router.add_adapter(Box::new(graphql));
1063
1064 assert!(router
1066 .route_request("graphql", "query { user }")
1067 .await
1068 .unwrap()
1069 .contains("get_user"));
1070
1071 assert!(router
1073 .route_request("graphql", "mutation { createUser }")
1074 .await
1075 .unwrap()
1076 .contains("create_user"));
1077 }
1078
1079 #[tokio::test]
1080 async fn test_integration_protocol_specific_features_grpc_streaming() {
1081 let mut router = Router::new();
1083 router.register("get_user", || async { "User".to_string() });
1084 router.register("list_users", || async { "Users".to_string() });
1085
1086 let mut grpc = GrpcAdapter::new();
1087 grpc.unary("UserService", "GetUser", "get_user");
1088 grpc.server_streaming("UserService", "ListUsers", "list_users");
1089 router.add_adapter(Box::new(grpc));
1090
1091 let unary_response = router
1093 .route_request("grpc", "UserService.GetUser:{}")
1094 .await
1095 .unwrap();
1096 assert!(unary_response.contains("unary"));
1097
1098 let streaming_response = router
1100 .route_request("grpc", "UserService.ListUsers:{}")
1101 .await
1102 .unwrap();
1103 assert!(streaming_response.contains("server_streaming"));
1104 }
1105}