1use std::{io::ErrorKind::WouldBlock, net::SocketAddr};
2
3use tokio::io::AsyncReadExt;
4use tokio::net::{TcpListener, TcpStream};
5
6use once_cell::sync::Lazy;
7use tokio::net::tcp::ReadHalf;
8
9use crate::request::Req;
10use crate::response::Res;
11use crate::route::{PathItemType, Route, RouteCallback};
12use crate::route_handler::RouteHandler;
13
14const BASE_ADDR: &str = "127.0.0.1";
15
16pub struct App<'a> {
17 pub routes: Vec<Route<'a>>,
18}
19
20static mut APP: Lazy<App<'static>> = Lazy::new(|| App { routes: vec![] });
21
22impl App<'static> {
23 pub fn new() -> &'static mut Lazy<App<'static>> {
24 unsafe { &mut APP }
25 }
26
27 #[tokio::main]
29 pub async fn listen<F>(&'static self, port: u16, on_bound: F)
30 where
31 F: FnOnce(),
32 {
33 let addr = format!("{}:{}", BASE_ADDR.to_owned(), port);
35
36 let listener = TcpListener::bind(addr.clone())
37 .await
38 .unwrap_or_else(|_| panic!("Can't bound at {}", addr));
39
40 on_bound();
41
42 loop {
43 let result = listener.accept().await;
44
45 tokio::spawn(async move {
46 match result {
47 Ok((stream, addr)) => self.handle_stream(stream, addr).await,
48 Err(err) => println!("Couldn't get client: {:?}", err),
49 }
50 });
51 }
52 }
53
54 async fn handle_stream<'a>(&'static self, mut socket: TcpStream, _addr: SocketAddr) {
55 let (mut read_half, write_half) = socket.split();
56
57 let raw_req = self.read_all(&mut read_half).await.unwrap();
58 let req = Req::new(&raw_req);
59 let res = Res::new();
60
61 match req {
62 Some(req) => {
63 let route = self.get_route(&req);
64
65 match route {
66 Some(r) => {
67 Res::send_outcome((r.callback)(req, res), write_half).await;
68 }
69 None => {
70 Res::send_outcome(res.status(404), write_half).await;
71 }
72 }
73 }
74 None => {
75 Res::send_outcome(res.status(400), write_half).await;
76 }
77 }
78 }
79
80 async fn read_all<'a>(&self, read_half: &mut ReadHalf<'a>) -> Result<String, std::io::Error> {
81 let mut buf: Vec<u8> = Vec::new();
83
84 let mut firs_read_buf = [0u8; 2024];
86 let bytes_read = read_half.read(&mut firs_read_buf).await.unwrap();
87 buf.extend_from_slice(&firs_read_buf[..bytes_read]);
88
89 loop {
90 let mut tmp_buf = [0u8; 1024];
93
94 match read_half.try_read(&mut tmp_buf) {
97 Ok(0) => break,
98 Ok(bytes_read) => buf.extend_from_slice(&tmp_buf[..bytes_read]),
99 Err(ref e) if e.kind() == WouldBlock => {
100 break;
101 }
102 Err(e) => {
103 return Err(e);
104 }
105 }
106 }
107
108 return Ok(std::str::from_utf8(&buf)
109 .unwrap()
110 .trim_matches(char::from(0))
111 .to_owned());
112 }
113
114 #[allow(dead_code)]
115 fn get_route<'a>(&'static self, req: &Req) -> Option<&Route<'a>> {
116 let mut res_route = None;
117
118 let req_paths = if req.path == "/" {
119 vec!["/"]
120 } else {
121 req.path.split_terminator('/').skip(1).collect::<Vec<_>>()
122 };
124
125 for route in &self.routes {
126 let mut is_compatible = true;
127
128 if route.paths.len() != req_paths.len() {
129 continue;
130 }
131
132 for (i, path) in route.paths.iter().enumerate().take(route.paths.len()) {
133 match path.r#type {
134 PathItemType::Static => {
135 if path.value != req_paths[i] {
136 is_compatible = false;
137 break;
138 }
139 }
140 PathItemType::Dynamic => (),
141 }
142 }
143
144 if is_compatible {
145 res_route = Some(route);
146 break;
147 }
148 }
149
150 res_route
151 }
152}
153
154impl RouteHandler for App<'_> {
155 fn get(&mut self, path: &'static str, handler: RouteCallback) -> &mut Self {
156 self.routes.push(Route::new(path, handler, Some("GET")));
157 self
158 }
159
160 fn post(&mut self, path: &'static str, handler: RouteCallback) -> &mut Self {
161 self.routes.push(Route::new(path, handler, Some("POST")));
162 self
163 }
164
165 fn put(&mut self, path: &'static str, handler: RouteCallback) -> &mut Self {
166 self.routes.push(Route::new(path, handler, Some("PUT")));
167 self
168 }
169
170 fn delete(&mut self, path: &'static str, handler: RouteCallback) -> &mut Self {
171 self.routes.push(Route::new(path, handler, Some("DELETE")));
172 self
173 }
174
175 fn patch(&mut self, path: &'static str, handler: RouteCallback) -> &mut Self {
176 self.routes.push(Route::new(path, handler, Some("PATCH")));
177 self
178 }
179}