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 handler: DynHandler = Arc::new(handler);
171 let route = format!("{}/{{*filepath}}", prefix);
172 if let Err(e) = self.router.insert("GET", &route, handler.clone()) {
173 panic!("Failed to register static file route {}: {}", route, e);
174 }
175 let root = if prefix.is_empty() { "/" } else { prefix };
178 let _ = self.router.insert("GET", root, handler.clone());
179 if !prefix.is_empty() {
180 let _ = self.router.insert("GET", &format!("{}/", prefix), handler);
181 }
182 self
183 }
184
185 pub async fn run(self, addr: &str) -> Result<()> {
187 let addr: SocketAddr = addr
188 .parse()
189 .map_err(|e| Error::internal(format!("Invalid address: {}", e)))?;
190
191 let listener = TcpListener::bind(addr)
192 .await
193 .map_err(|e| Error::internal(format!("Failed to bind: {}", e)))?;
194
195 println!("š ullun-api listening on http://{}", addr);
196
197 let router = Arc::new(self.router);
198 let middlewares = Arc::new(self.middlewares);
199 let max_body_size = self.max_body_size;
200
201 let shutdown = async {
203 tokio::signal::ctrl_c()
204 .await
205 .expect("Failed to install CTRL+C handler");
206 println!("\nš Shutting down gracefully...");
207 };
208
209 tokio::select! {
210 _ = shutdown => {
211 println!("ā
Server stopped");
212 Ok(())
213 }
214 result = Self::serve_loop(listener, router, middlewares, max_body_size) => result
215 }
216 }
217
218 pub async fn serve(self, listener: TcpListener) -> Result<()> {
224 Self::serve_loop(
225 listener,
226 Arc::new(self.router),
227 Arc::new(self.middlewares),
228 self.max_body_size,
229 )
230 .await
231 }
232
233 async fn serve_loop(
234 listener: TcpListener,
235 router: Arc<Router>,
236 middlewares: Arc<Vec<Arc<dyn Middleware>>>,
237 max_body_size: Option<usize>,
238 ) -> Result<()> {
239 loop {
240 let (stream, _) = listener
241 .accept()
242 .await
243 .map_err(|e| Error::internal(format!("Failed to accept: {}", e)))?;
244
245 let io = TokioIo::new(stream);
246 let router = router.clone();
247 let middlewares = middlewares.clone();
248
249 tokio::task::spawn(async move {
250 if let Err(err) = http1::Builder::new()
251 .serve_connection(
252 io,
253 service_fn(|req| {
254 let router = router.clone();
255 let middlewares = middlewares.clone();
256 async move {
257 Ok::<_, Infallible>(
258 handle_request(req, router, middlewares, max_body_size).await,
259 )
260 }
261 }),
262 )
263 .await
264 {
265 eprintln!("Error serving connection: {:?}", err);
266 }
267 });
268 }
269 }
270}
271
272impl Default for App {
273 fn default() -> Self {
274 Self::new()
275 }
276}
277
278impl RouteGroup {
279 fn new(prefix: &str) -> Self {
280 let prefix = prefix.trim_end_matches('/');
281 Self {
282 prefix: prefix.to_string(),
283 routes: Vec::new(),
284 middlewares: Vec::new(),
285 }
286 }
287
288 pub fn get<H>(mut self, path: &str, handler: H) -> Self
289 where
290 H: Handler,
291 {
292 self.routes.push((
293 "GET".to_string(),
294 path.to_string(),
295 Arc::new(handler) as DynHandler,
296 ));
297 self
298 }
299
300 pub fn post<H>(mut self, path: &str, handler: H) -> Self
301 where
302 H: Handler,
303 {
304 self.routes.push((
305 "POST".to_string(),
306 path.to_string(),
307 Arc::new(handler) as DynHandler,
308 ));
309 self
310 }
311
312 pub fn put<H>(mut self, path: &str, handler: H) -> Self
313 where
314 H: Handler,
315 {
316 self.routes.push((
317 "PUT".to_string(),
318 path.to_string(),
319 Arc::new(handler) as DynHandler,
320 ));
321 self
322 }
323
324 pub fn delete<H>(mut self, path: &str, handler: H) -> Self
325 where
326 H: Handler,
327 {
328 self.routes.push((
329 "DELETE".to_string(),
330 path.to_string(),
331 Arc::new(handler) as DynHandler,
332 ));
333 self
334 }
335
336 pub fn patch<H>(mut self, path: &str, handler: H) -> Self
337 where
338 H: Handler,
339 {
340 self.routes.push((
341 "PATCH".to_string(),
342 path.to_string(),
343 Arc::new(handler) as DynHandler,
344 ));
345 self
346 }
347
348 pub fn middleware<M>(mut self, middleware: M) -> Self
349 where
350 M: Middleware,
351 {
352 self.middlewares.push(Arc::new(middleware));
353 self
354 }
355}
356
357async fn handle_request(
358 req: hyper::Request<hyper::body::Incoming>,
359 router: Arc<Router>,
360 middlewares: Arc<Vec<Arc<dyn Middleware>>>,
361 max_body_size: Option<usize>,
362) -> hyper::Response<http_body_util::Full<bytes::Bytes>> {
363 let method = req.method().to_string();
364 let path = req.uri().path().to_string();
365
366 let (parts, body) = req.into_parts();
368
369 let body_bytes = if let Some(max_size) = max_body_size {
371 if let Some(content_length) = parts.headers.get(http::header::CONTENT_LENGTH) {
373 if let Ok(length_str) = content_length.to_str() {
374 if let Ok(length) = length_str.parse::<usize>() {
375 if length > max_size {
376 let error_response = Response::from_error(Error::custom(
377 413,
378 format!("Request body too large (max {} bytes)", max_size),
379 ));
380 return error_response.into_hyper();
381 }
382 }
383 }
384 }
385
386 let limited = http_body_util::Limited::new(body, max_size);
388 match limited.collect().await {
389 Ok(collected) => collected.to_bytes(),
390 Err(_) => {
391 let error_response = Response::from_error(Error::custom(
393 413,
394 format!("Request body too large (max {} bytes)", max_size),
395 ));
396 return error_response.into_hyper();
397 }
398 }
399 } else {
400 match body.collect().await {
401 Ok(collected) => collected.to_bytes(),
402 Err(_) => bytes::Bytes::new(),
403 }
404 };
405
406 let mut request = Request::new(parts.method, parts.uri, parts.headers, body_bytes);
407
408 let handler: Option<DynHandler> = match router.match_route(&method, &path) {
411 Ok((handler, params)) => {
412 request.params = params;
413 Some(handler)
414 }
415 Err(_) => None,
416 };
417
418 let result = if middlewares.is_empty() {
419 dispatch(handler, request).await
420 } else {
421 let mut chain = middlewares.to_vec();
423 let final_handler = Arc::new(move |req: Request, _next: Next| {
424 let handler = handler.clone();
425 async move { dispatch(handler, req).await }
426 });
427 chain.push(final_handler as Arc<dyn Middleware>);
428
429 Next::new(Arc::new(chain)).run(request).await
430 };
431
432 let response = match result {
434 Ok(resp) => resp,
435 Err(err) => Response::from_error(err),
436 };
437
438 response.into_hyper()
439}
440
441async fn dispatch(handler: Option<DynHandler>, req: Request) -> Result<Response> {
442 match handler {
443 Some(handler) => handler.call(req).await,
444 None => Err(Error::not_found("Route not found")),
445 }
446}