1use crate::error::{Error, Result};
4use crate::handler::{DynHandler, Handler, HandlerWithParams};
5use crate::middleware::{Middleware, Next};
6use crate::request::{Params, Request};
7use crate::response::Response;
8use crate::router::Router;
9use http_body_util::BodyExt;
10use hyper::server::conn::http1;
11use hyper::service::service_fn;
12use hyper_util::rt::TokioIo;
13use std::convert::Infallible;
14use std::net::SocketAddr;
15use std::sync::Arc;
16use tokio::net::TcpListener;
17
18pub struct App {
20 router: Router,
21 middlewares: Vec<Arc<dyn Middleware>>,
22 max_body_size: Option<usize>, }
24
25pub struct RouteGroup {
27 prefix: String,
28 routes: Vec<(String, String, DynHandler)>, middlewares: Vec<Arc<dyn Middleware>>,
30}
31
32impl App {
33 pub fn new() -> Self {
34 Self {
35 router: Router::new(),
36 middlewares: Vec::new(),
37 max_body_size: Some(10 * 1024 * 1024), }
39 }
40
41 pub fn max_body_size(mut self, size: Option<usize>) -> Self {
43 self.max_body_size = size;
44 self
45 }
46
47 pub fn group(mut self, prefix: &str, configure: impl FnOnce(RouteGroup) -> RouteGroup) -> Self {
49 let group = RouteGroup::new(prefix);
50 let group = configure(group);
51
52 for (method, path, handler) in group.routes {
54 let full_path = format!("{}{}", group.prefix, path);
55 if let Err(e) = self.router.insert(&method, &full_path, handler) {
56 panic!("Failed to register {} route {}: {}", method, full_path, e);
57 }
58 }
59
60 if !group.middlewares.is_empty() {
63 eprintln!("Warning: RouteGroup.middleware() is not yet implemented. Middlewares will be ignored.");
64 }
65
66 self
67 }
68
69 pub fn get<H>(mut self, path: &str, handler: H) -> Self
71 where
72 H: Handler,
73 {
74 if let Err(e) = self
75 .router
76 .insert("GET", path, Arc::new(handler) as DynHandler)
77 {
78 panic!("Failed to register GET route {}: {}", path, e);
79 }
80 self
81 }
82
83 pub fn get_with_params<F, Fut>(mut self, path: &str, handler: F) -> Self
85 where
86 F: Fn(Params) -> Fut + Send + Sync + 'static,
87 Fut: std::future::Future<Output = Result<Response>> + Send + 'static,
88 {
89 if let Err(e) = self.router.insert(
90 "GET",
91 path,
92 Arc::new(HandlerWithParams::new(handler)) as DynHandler,
93 ) {
94 panic!("Failed to register GET route {}: {}", path, e);
95 }
96 self
97 }
98
99 pub fn post<H>(mut self, path: &str, handler: H) -> Self
101 where
102 H: Handler,
103 {
104 if let Err(e) = self
105 .router
106 .insert("POST", path, Arc::new(handler) as DynHandler)
107 {
108 panic!("Failed to register POST route {}: {}", path, e);
109 }
110 self
111 }
112
113 pub fn put<H>(mut self, path: &str, handler: H) -> Self
115 where
116 H: Handler,
117 {
118 if let Err(e) = self
119 .router
120 .insert("PUT", path, Arc::new(handler) as DynHandler)
121 {
122 panic!("Failed to register PUT route {}: {}", path, e);
123 }
124 self
125 }
126
127 pub fn delete<H>(mut self, path: &str, handler: H) -> Self
129 where
130 H: Handler,
131 {
132 if let Err(e) = self
133 .router
134 .insert("DELETE", path, Arc::new(handler) as DynHandler)
135 {
136 panic!("Failed to register DELETE route {}: {}", path, e);
137 }
138 self
139 }
140
141 pub fn patch<H>(mut self, path: &str, handler: H) -> Self
143 where
144 H: Handler,
145 {
146 if let Err(e) = self
147 .router
148 .insert("PATCH", path, Arc::new(handler) as DynHandler)
149 {
150 panic!("Failed to register PATCH route {}: {}", path, e);
151 }
152 self
153 }
154
155 pub fn middleware<M>(mut self, middleware: M) -> Self
157 where
158 M: Middleware,
159 {
160 self.middlewares.push(Arc::new(middleware));
161 self
162 }
163
164 pub fn serve_static(mut self, route_prefix: &str, dir_path: &str) -> Self {
166 use crate::static_files::StaticFileHandler;
167 let handler = StaticFileHandler::new(dir_path);
168 let prefix = route_prefix.trim_end_matches('/');
170 let route = format!("{}/*filepath", prefix);
171 if let Err(e) = self.router.insert("GET", &route, Arc::new(handler) as DynHandler) {
172 panic!("Failed to register static file route {}: {}", route, e);
173 }
174 self
175 }
176
177 pub async fn run(self, addr: &str) -> Result<()> {
179 let addr: SocketAddr = addr
180 .parse()
181 .map_err(|e| Error::internal(format!("Invalid address: {}", e)))?;
182
183 let listener = TcpListener::bind(addr)
184 .await
185 .map_err(|e| Error::internal(format!("Failed to bind: {}", e)))?;
186
187 println!("š ullun-api listening on http://{}", addr);
188
189 let router = Arc::new(self.router);
190 let middlewares = Arc::new(self.middlewares);
191 let max_body_size = self.max_body_size;
192
193 let shutdown = async {
195 tokio::signal::ctrl_c()
196 .await
197 .expect("Failed to install CTRL+C handler");
198 println!("\nš Shutting down gracefully...");
199 };
200
201 tokio::select! {
202 _ = shutdown => {
203 println!("ā
Server stopped");
204 Ok(())
205 }
206 result = Self::serve_loop(listener, router, middlewares, max_body_size) => result
207 }
208 }
209
210 async fn serve_loop(
211 listener: TcpListener,
212 router: Arc<Router>,
213 middlewares: Arc<Vec<Arc<dyn Middleware>>>,
214 max_body_size: Option<usize>,
215 ) -> Result<()> {
216 loop {
217 let (stream, _) = listener
218 .accept()
219 .await
220 .map_err(|e| Error::internal(format!("Failed to accept: {}", e)))?;
221
222 let io = TokioIo::new(stream);
223 let router = router.clone();
224 let middlewares = middlewares.clone();
225
226 tokio::task::spawn(async move {
227 if let Err(err) = http1::Builder::new()
228 .serve_connection(
229 io,
230 service_fn(|req| {
231 let router = router.clone();
232 let middlewares = middlewares.clone();
233 async move {
234 Ok::<_, Infallible>(
235 handle_request(req, router, middlewares, max_body_size).await,
236 )
237 }
238 }),
239 )
240 .await
241 {
242 eprintln!("Error serving connection: {:?}", err);
243 }
244 });
245 }
246 }
247}
248
249impl Default for App {
250 fn default() -> Self {
251 Self::new()
252 }
253}
254
255impl RouteGroup {
256 fn new(prefix: &str) -> Self {
257 let prefix = prefix.trim_end_matches('/');
258 Self {
259 prefix: prefix.to_string(),
260 routes: Vec::new(),
261 middlewares: Vec::new(),
262 }
263 }
264
265 pub fn get<H>(mut self, path: &str, handler: H) -> Self
266 where
267 H: Handler,
268 {
269 self.routes.push(("GET".to_string(), path.to_string(), Arc::new(handler) as DynHandler));
270 self
271 }
272
273 pub fn post<H>(mut self, path: &str, handler: H) -> Self
274 where
275 H: Handler,
276 {
277 self.routes.push(("POST".to_string(), path.to_string(), Arc::new(handler) as DynHandler));
278 self
279 }
280
281 pub fn put<H>(mut self, path: &str, handler: H) -> Self
282 where
283 H: Handler,
284 {
285 self.routes.push(("PUT".to_string(), path.to_string(), Arc::new(handler) as DynHandler));
286 self
287 }
288
289 pub fn delete<H>(mut self, path: &str, handler: H) -> Self
290 where
291 H: Handler,
292 {
293 self.routes.push(("DELETE".to_string(), path.to_string(), Arc::new(handler) as DynHandler));
294 self
295 }
296
297 pub fn patch<H>(mut self, path: &str, handler: H) -> Self
298 where
299 H: Handler,
300 {
301 self.routes.push(("PATCH".to_string(), path.to_string(), Arc::new(handler) as DynHandler));
302 self
303 }
304
305 pub fn middleware<M>(mut self, middleware: M) -> Self
306 where
307 M: Middleware,
308 {
309 self.middlewares.push(Arc::new(middleware));
310 self
311 }
312}
313
314async fn handle_request(
315 req: hyper::Request<hyper::body::Incoming>,
316 router: Arc<Router>,
317 middlewares: Arc<Vec<Arc<dyn Middleware>>>,
318 max_body_size: Option<usize>,
319) -> hyper::Response<http_body_util::Full<bytes::Bytes>> {
320 let method = req.method().to_string();
321 let path = req.uri().path().to_string();
322
323 let (parts, body) = req.into_parts();
325
326 let body_bytes = if let Some(max_size) = max_body_size {
328 if let Some(content_length) = parts.headers.get(http::header::CONTENT_LENGTH) {
330 if let Ok(length_str) = content_length.to_str() {
331 if let Ok(length) = length_str.parse::<usize>() {
332 if length > max_size {
333 let error_response = Response::from_error(Error::custom(
334 413,
335 format!("Request body too large (max {} bytes)", max_size),
336 ));
337 return error_response.into_hyper();
338 }
339 }
340 }
341 }
342
343 let limited = http_body_util::Limited::new(body, max_size);
345 match limited.collect().await {
346 Ok(collected) => collected.to_bytes(),
347 Err(_) => {
348 let error_response = Response::from_error(Error::custom(
350 413,
351 format!("Request body too large (max {} bytes)", max_size),
352 ));
353 return error_response.into_hyper();
354 }
355 }
356 } else {
357 match body.collect().await {
358 Ok(collected) => collected.to_bytes(),
359 Err(_) => bytes::Bytes::new(),
360 }
361 };
362
363 let mut request = Request::new(parts.method, parts.uri, parts.headers, body_bytes);
364
365 let result = match router.match_route(&method, &path) {
367 Ok((handler, params)) => {
368 request.params = params;
369
370 if middlewares.is_empty() {
372 handler.call(request).await
373 } else {
374 let mut chain = middlewares.to_vec();
376
377 let final_handler = Arc::new(move |req: Request, _next: Next| {
379 let h = handler.clone();
380 async move { h.call(req).await }
381 });
382 chain.push(final_handler as Arc<dyn Middleware>);
383
384 let next = Next::new(Arc::new(chain));
385 next.run(request).await
386 }
387 }
388 Err(e) => Err(e),
389 };
390
391 let response = match result {
393 Ok(resp) => resp,
394 Err(err) => Response::from_error(err),
395 };
396
397 response.into_hyper()
398}