ferro_rs/routing/
group.rs1use super::{BoxedHandler, RouteBuilder, Router};
4use crate::http::{Request, Response};
5use crate::middleware::{into_boxed, BoxedMiddleware, Middleware};
6use std::future::Future;
7use std::sync::Arc;
8
9pub struct GroupBuilder {
21 outer_router: Router,
23 group_routes: Vec<GroupRoute>,
25 prefix: String,
27 middleware: Vec<BoxedMiddleware>,
29}
30
31struct GroupRoute {
33 method: GroupMethod,
34 path: String,
35 handler: Arc<BoxedHandler>,
36}
37
38#[derive(Clone, Copy)]
39enum GroupMethod {
40 Get,
41 Post,
42 Put,
43 Delete,
44}
45
46impl GroupBuilder {
47 pub fn middleware<M: Middleware + 'static>(mut self, middleware: M) -> Self {
57 self.middleware.push(into_boxed(middleware));
58 self
59 }
60
61 fn finalize(mut self) -> Router {
63 for route in self.group_routes {
65 let full_path = format!("{}{}", self.prefix, route.path);
66
67 match route.method {
69 GroupMethod::Get => {
70 self.outer_router.insert_get(&full_path, route.handler);
71 }
72 GroupMethod::Post => {
73 self.outer_router.insert_post(&full_path, route.handler);
74 }
75 GroupMethod::Put => {
76 self.outer_router.insert_put(&full_path, route.handler);
77 }
78 GroupMethod::Delete => {
79 self.outer_router.insert_delete(&full_path, route.handler);
80 }
81 }
82
83 for mw in &self.middleware {
85 self.outer_router.add_middleware(&full_path, mw.clone());
86 }
87 }
88
89 self.outer_router
90 }
91}
92
93pub struct GroupRouter {
97 routes: Vec<GroupRoute>,
98}
99
100impl GroupRouter {
101 fn new() -> Self {
102 Self { routes: Vec::new() }
103 }
104
105 pub fn get<H, Fut>(mut self, path: &str, handler: H) -> Self
107 where
108 H: Fn(Request) -> Fut + Send + Sync + 'static,
109 Fut: Future<Output = Response> + Send + 'static,
110 {
111 let boxed: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
112 self.routes.push(GroupRoute {
113 method: GroupMethod::Get,
114 path: path.to_string(),
115 handler: Arc::new(boxed),
116 });
117 self
118 }
119
120 pub fn post<H, Fut>(mut self, path: &str, handler: H) -> Self
122 where
123 H: Fn(Request) -> Fut + Send + Sync + 'static,
124 Fut: Future<Output = Response> + Send + 'static,
125 {
126 let boxed: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
127 self.routes.push(GroupRoute {
128 method: GroupMethod::Post,
129 path: path.to_string(),
130 handler: Arc::new(boxed),
131 });
132 self
133 }
134
135 pub fn put<H, Fut>(mut self, path: &str, handler: H) -> Self
137 where
138 H: Fn(Request) -> Fut + Send + Sync + 'static,
139 Fut: Future<Output = Response> + Send + 'static,
140 {
141 let boxed: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
142 self.routes.push(GroupRoute {
143 method: GroupMethod::Put,
144 path: path.to_string(),
145 handler: Arc::new(boxed),
146 });
147 self
148 }
149
150 pub fn delete<H, Fut>(mut self, path: &str, handler: H) -> Self
152 where
153 H: Fn(Request) -> Fut + Send + Sync + 'static,
154 Fut: Future<Output = Response> + Send + 'static,
155 {
156 let boxed: BoxedHandler = Box::new(move |req| Box::pin(handler(req)));
157 self.routes.push(GroupRoute {
158 method: GroupMethod::Delete,
159 path: path.to_string(),
160 handler: Arc::new(boxed),
161 });
162 self
163 }
164}
165
166impl Router {
167 pub fn group<F>(self, prefix: &str, builder_fn: F) -> GroupBuilder
184 where
185 F: FnOnce(GroupRouter) -> GroupRouter,
186 {
187 let inner = GroupRouter::new();
188 let built = builder_fn(inner);
189
190 GroupBuilder {
191 outer_router: self,
192 group_routes: built.routes,
193 prefix: prefix.to_string(),
194 middleware: Vec::new(),
195 }
196 }
197}
198
199impl From<GroupBuilder> for Router {
200 fn from(builder: GroupBuilder) -> Self {
201 builder.finalize()
202 }
203}
204
205impl RouteBuilder {
207 pub fn group<F>(self, prefix: &str, builder_fn: F) -> GroupBuilder
209 where
210 F: FnOnce(GroupRouter) -> GroupRouter,
211 {
212 self.router.group(prefix, builder_fn)
213 }
214}