From 4d0d6e64a5d986bf5bf1c4323139ff41e784b7a3 Mon Sep 17 00:00:00 2001 From: elcharitas Date: Sat, 14 Dec 2024 21:29:24 +0100 Subject: [PATCH] feat: grouped roputes and router --- crates/core/src/lib.rs | 2 +- crates/shared/src/core/engine.rs | 84 ++++++++++++++++++++------------ crates/swagger/src/lib.rs | 1 + crates/ws/src/lib.rs | 4 +- 4 files changed, 57 insertions(+), 34 deletions(-) diff --git a/crates/core/src/lib.rs b/crates/core/src/lib.rs index adbe664..9fe85cf 100644 --- a/crates/core/src/lib.rs +++ b/crates/core/src/lib.rs @@ -14,7 +14,7 @@ pub mod prelude { pub use ngyn_hyper::HyperApplication; pub use ngyn_shared::{ core::{ - engine::{NgynEngine, NgynHttpEngine}, + engine::{NgynEngine, NgynHttpEngine, RouteInstance}, handler::*, }, server::{ diff --git a/crates/shared/src/core/engine.rs b/crates/shared/src/core/engine.rs index 3315290..3af300c 100644 --- a/crates/shared/src/core/engine.rs +++ b/crates/shared/src/core/engine.rs @@ -1,6 +1,6 @@ use bytes::Bytes; use http::Request; -use matchit::{Match, Router}; +use matchit::{Match, MergeError, Router}; use std::sync::Arc; use super::handler::{handler, RouteHandler}; @@ -9,6 +9,17 @@ use crate::{ Middleware, NgynMiddleware, }; +#[derive(Default)] +pub struct GroupRouter { + router: Router, +} + +impl RouteInstance for GroupRouter { + fn router_mut(&mut self) -> &mut Router { + &mut self.router + } +} + #[derive(Default)] pub struct PlatformData { router: Router, @@ -69,6 +80,22 @@ impl PlatformData { cx.response } + /// Adds a middleware to the platform data. + /// + /// ### Arguments + /// + /// * `middleware` - The middleware to add. + pub(self) fn add_middleware(&mut self, middleware: Box) { + self.middlewares.push(middleware); + } +} + +pub trait NgynPlatform: Default { + fn data_mut(&mut self) -> &mut PlatformData; +} + +pub trait RouteInstance { + fn router_mut(&mut self) -> &mut Router; /// Adds a route to the platform data. /// /// ### Arguments @@ -76,7 +103,7 @@ impl PlatformData { /// * `path` - The path of the route. /// * `method` - The HTTP method of the route. /// * `handler` - The handler function for the route. - pub fn add_route(&mut self, path: &str, method: Option, handler: RouteHandler) { + fn add_route(&mut self, path: &str, method: Option, handler: RouteHandler) { let method = method .map(|method| method.to_string()) .unwrap_or_else(|| "{METHOD}".to_string()); @@ -87,28 +114,9 @@ impl PlatformData { method + "/" + path }; - self.router.insert(route, handler).unwrap(); - } - - /// Adds a middleware to the platform data. - /// - /// ### Arguments - /// - /// * `middleware` - The middleware to add. - pub(self) fn add_middleware(&mut self, middleware: Box) { - self.middlewares.push(middleware); + self.router_mut().insert(route, handler).unwrap(); } -} -pub trait NgynPlatform: Default { - fn data_mut(&mut self) -> &mut PlatformData; -} - -pub trait NgynHttpPlatform: Default { - fn data_mut(&mut self) -> &mut PlatformData; -} - -pub trait NgynHttpEngine: NgynEngine { /// Adds a route to the application. /// /// ### Arguments @@ -128,8 +136,7 @@ pub trait NgynHttpEngine: NgynEngine { /// engine.route('/', Method::GET, Box::new(|_, _| {})); /// ``` fn route(&mut self, path: &str, method: Method, handler: impl Into) { - self.data_mut() - .add_route(path, Some(method), handler.into()); + self.add_route(path, Some(method), handler.into()); } /// Adds a new route to the `NgynApplication` with the `Method::Get`. @@ -161,7 +168,13 @@ pub trait NgynHttpEngine: NgynEngine { fn head(&mut self, path: &str, handler: impl Into) { self.route(path, Method::HEAD, handler.into()) } +} + +pub trait NgynHttpPlatform: Default { + fn data_mut(&mut self) -> &mut PlatformData; +} +pub trait NgynHttpEngine: NgynPlatform { /// Sets up static file routes. /// /// This is great for apps tha would want to output files in a specific folder. @@ -192,7 +205,15 @@ pub trait NgynHttpEngine: NgynEngine { pub trait NgynEngine: NgynPlatform { fn any(&mut self, path: &str, handler: impl Into) { - self.data_mut().add_route(path, None, handler.into()); + self.add_route(path, None, handler.into()); + } + + fn group(&mut self, registry: impl Fn(&mut GroupRouter)) -> Result<(), MergeError> { + let mut group = GroupRouter { + router: Router::::new(), + }; + registry(&mut group); + self.data_mut().router.merge(group.router) } /// Adds a middleware to the application. @@ -221,6 +242,11 @@ impl NgynPlatform for T { } impl NgynEngine for T {} +impl RouteInstance for T { + fn router_mut(&mut self) -> &mut Router { + &mut self.data_mut().router + } +} impl NgynHttpEngine for T {} #[cfg(test)] @@ -316,9 +342,7 @@ mod tests { async fn test_respond_with_route_handler() { let mut engine = MockEngine::default(); let handler: Box = Box::new(|_| {}); - engine - .data_mut() - .add_route("/test", Some(Method::GET), RouteHandler::Sync(handler)); + engine.add_route("/test", Some(Method::GET), RouteHandler::Sync(handler)); let req = Request::builder() .method(Method::GET) @@ -369,9 +393,7 @@ mod tests { async fn test_add_route() { let mut engine = MockEngine::default(); let handler: Box = Box::new(|_| {}); - engine - .data_mut() - .add_route("/test", Some(Method::GET), RouteHandler::Sync(handler)); + engine.add_route("/test", Some(Method::GET), RouteHandler::Sync(handler)); assert!(engine.data.router.at("GET/test").is_ok()); } diff --git a/crates/swagger/src/lib.rs b/crates/swagger/src/lib.rs index 9f8da5e..83ef4fa 100644 --- a/crates/swagger/src/lib.rs +++ b/crates/swagger/src/lib.rs @@ -1,3 +1,4 @@ +use ngyn::shared::core::engine::RouteInstance; use ngyn::shared::{ core::{ engine::{NgynHttpEngine, PlatformData}, diff --git a/crates/ws/src/lib.rs b/crates/ws/src/lib.rs index 006e8ee..1231ab7 100644 --- a/crates/ws/src/lib.rs +++ b/crates/ws/src/lib.rs @@ -1,5 +1,5 @@ use core::fmt; -use ngyn_shared::core::engine::{NgynPlatform, PlatformData}; +use ngyn_shared::core::engine::{NgynPlatform, PlatformData, RouteInstance}; use ngyn_shared::core::handler::RouteHandler; use ngyn_shared::server::response::ReadBytes; use ngyn_shared::server::NgynRequest; @@ -25,7 +25,7 @@ impl NgynPlatform for WebsocketApplication { impl WebsocketApplication { /// add a route to handle pub fn route(&mut self, path: &str, handler: impl Into) { - self.data_mut().add_route(path, None, handler.into()); + self.add_route(path, None, handler.into()); } // Broadcast message to all connected clients