1use bytes::Bytes;
2use hyper::{
3 body::to_bytes,
4 service::{make_service_fn, service_fn},
5 Body, Request, Server,
6};
7use route_recognizer::Params;
8use router::Router;
9use std::sync::Arc;
10
11type Response = hyper::Response<hyper::Body>;
12type Error = Box<dyn std::error::Error + Send + Sync + 'static>;
13
14#[derive(Clone, Debug)]
15pub struct AppState {
16 pub state_thing: String,
17}
18
19#[derive(Debug)]
20pub struct Context {
21 pub state: AppState,
22 pub req: Request<Body>,
23 pub params: Params,
24 body_bytes: Option<Bytes>,
25}
26
27impl Context {
28 pub fn new(state: AppState, req: Request<Body>, params: Params) -> Context {
29 Context {
30 state,
31 req,
32 params,
33 body_bytes: None,
34 }
35 }
36
37 pub async fn body_json<T: serde::de::DeserializeOwned>(&mut self) -> Result<T, Error> {
38 let body_bytes = match self.body_bytes {
39 Some(ref v) => v,
40 _ => {
41 let body = to_bytes(self.req.body_mut()).await?;
42 self.body_bytes = Some(body);
43 self.body_bytes.as_ref().expect("body_bytes was set above")
44 }
45 };
46 Ok(serde_json::from_slice(&body_bytes)?)
47 }
48}
49
50
51
52pub mod headers;
53pub mod parser;
54pub mod request;
55pub mod response;
56pub mod status;
57pub mod router;
58pub mod handler;
59
60pub mod paths {
61 use crate::request::Request;
62 use crate::response::Response;
63
64 pub type Paths = Vec<Path<fn(Request, Response)>>;
65 pub type SinglePath = Path<fn(Request, Response)>;
66
67 pub struct Path<T> {
69 pub name: String,
70 pub view: T,
71 }
72
73 impl<T> Path<T> {
74 pub fn new(name: &str, view: T) -> Self {
75 let name = name.to_string();
76
77 return Self { name, view };
78 }
79 }
80}
81
82pub mod server {
83 use crate::headers::{extract_headers, parse_request_method_header};
84 use crate::paths::{Paths, SinglePath};
85 use crate::request::Request;
86 use crate::response::Response;
87 use std::net::{Shutdown, TcpListener, TcpStream, Ipv4Addr, UdpSocket};
88 use std::sync::atomic::{AtomicBool, Ordering};
89 use std::sync::{Arc, RwLock};
90 use std::thread::spawn;
91
92 use std::str::FromStr;
116 pub type Port = u16;
117
118
119 pub fn is_tcp_port_available(host: &str, p: Port) -> bool {
120 matches!(
121 TcpListener::bind((Ipv4Addr::from_str(host).unwrap(), p)).is_ok(),
122 true
123 )
124 }
125
126 pub fn is_udp_port_available(host: &str, p: Port) -> bool {
127 matches!(
128 UdpSocket::bind((Ipv4Addr::from_str(host).unwrap(), p)).is_ok(),
129 true
130 )
131 }
132
133 pub fn check_port(host: &str, port: Port) -> bool {
134 is_tcp_port_available(host, port) && is_udp_port_available(host, port)
135 }
136
137
138 #[cfg(test)]
139 mod tests {
140 #[cfg(test)]
141 use crate::server::check_port;
142 fn test_is_free() {
143 assert!(check_port("127.0.0.1", 32200));
144 }
145 }
146
147
148 pub fn get_available_port() -> Option<u16> {
149 (8000..9000).find(|port| port_is_available(*port))
150 }
151
152 pub fn port_is_available(port: u16) -> bool {
153 match TcpListener::bind(("0.0.0.0", port)) {
154 Ok(_) => true,
155 Err(_) => false,
156 }
157 }
158
159 pub fn run_server(listen_address: &str, paths: Paths) {
160 println!("\nhttp://{}", listen_address);
161
162 let v: Vec<&str> = listen_address.split(":").collect();
163 print!("\nv[0]={:?}", v[0]);
164 print!("\nv[1]={:?}", v[1]);
165
166 if port_is_available(8080 as u16) {
171 print!("\n8080 port_is_available");
172 } else {
174 print!("\nNOT!!! 8080 port_is_available");
175 std::process::exit(0);
176 }
177 let tcp = TcpListener::bind(listen_address);
187
188 match tcp {
189 Ok(listener) => {
190 listen_connections(listener, paths);
191 }
192
193 Err(_) => {
194 eprintln!("Failed to listen stream");
195 }
196 }
197 }
198
199 pub fn listen_connections(listener: TcpListener, paths: Paths) {
200 let paths_lock = Arc::new(RwLock::new(paths));
201
202 for stream in listener.incoming() {
203 match stream {
204 Ok(stream) => {
205 let paths = Arc::clone(&paths_lock);
206
207 spawn(move || {
208 serve_client(stream, paths);
209 });
210 }
211
212 Err(error) => {
213 print!("Error receiving stream: {}", error);
214 }
215 }
216 }
217 }
218
219 pub struct Context {
220 pub accept_next: AtomicBool,
224 }
225
226 impl Context {
227 pub fn dont_wait(&self) {
228 self.accept_next.store(false, Ordering::Relaxed);
229 }
230 }
231
232 fn serve_client(stream: TcpStream, paths: Arc<RwLock<Paths>>) {
233 let context = Context {
234 accept_next: AtomicBool::new(true),
235 };
236
237 let context_ref = Arc::new(context);
238
239 while context_ref.accept_next.load(Ordering::Relaxed) {
240 let stream = stream.try_clone().expect("Error cloning stream");
241 decode_request(stream, paths.clone(), context_ref.clone());
242 }
243 }
244
245 pub fn decode_request(mut stream: TcpStream, paths: Arc<RwLock<Paths>>, context: Arc<Context>) {
246 let mut header_start = String::new();
247 let mut partial_body_bytes = Vec::new();
248
249 const MAX_HEADER_SIZE: usize = 1024 * 1024; let headers_result = extract_headers(
251 &mut stream,
252 &mut header_start,
253 &mut partial_body_bytes,
254 MAX_HEADER_SIZE,
255 );
256
257 if !headers_result.is_ok() {
258 context.accept_next.store(false, Ordering::Relaxed);
259 return;
260 }
261
262 let headers = headers_result.unwrap();
263
264 let request_info = parse_request_method_header(&header_start.as_str());
265 if !request_info.is_some() {
266 context.accept_next.store(false, Ordering::Relaxed);
267 let _ = stream.shutdown(Shutdown::Both);
268 return;
269 }
270
271 let (method, raw_path) = request_info.unwrap();
272
273 let body_read = Arc::new(AtomicBool::from(false));
275 let body_parsed = Arc::new(AtomicBool::from(false));
276
277 let mut request = Request::new(
278 context,
279 stream,
280 method,
281 raw_path,
282 headers,
283 body_read.clone(),
284 body_parsed.clone(),
285 );
286 request.setup();
287
288 request.set_partial_body_bytes(partial_body_bytes);
290
291 let mut matched_view: Option<&SinglePath> = None;
292
293 let binding = paths.read().unwrap();
294 for path in binding.iter() {
295 if request.pathname == path.name {
296 matched_view = Some(&path);
297 }
298 }
299
300 if let Some(view) = matched_view {
301 serve_page(request, view);
302 } else {
303 serve_not_found(request);
304 }
305 }
306
307 fn serve_page(request: Request, matched_path: &SinglePath) {
308 let response = Response::new(request.clone());
309 (matched_path.view)(request, response);
310 }
311
312 fn serve_not_found(request: Request) {
313 let mut response = Response::new(request);
314 response.html(404, "404 NOT FOUND".to_string());
315 response.send();
316 }
317}