1pub mod status;
2pub mod parser;
3pub mod request;
4pub mod headers;
5pub mod response;
6
7pub mod paths {
8 use crate::request::Request;
9 use crate::response::Response;
10
11 pub type Paths = Vec<Path<fn(Request, Response)>>;
12 pub type SinglePath = Path<fn(Request, Response)>;
13
14 pub struct Path<T> {
16 pub name: String,
17 pub view: T,
18 }
19
20 impl<T> Path<T> {
21 pub fn new(name: &str, view: T) -> Self {
22 let name = name.to_string();
23
24 return Self {
25 name,
26 view,
27 };
28 }
29 }
30}
31
32
33pub mod server {
34 use std::net::{Shutdown, TcpListener, TcpStream};
35 use std::sync::{Arc, RwLock};
36 use std::sync::atomic::{AtomicBool, Ordering};
37 use std::thread::spawn;
38 use crate::headers::{parse_request_method_header, extract_headers};
39 use crate::paths::{Paths, SinglePath};
40 use crate::request::{Request};
41 use crate::response::Response;
42
43 pub fn run_server(listen_address: &str, paths: Paths) {
64 println!("Running server in: http://{}", listen_address);
65 let tcp = TcpListener::bind(listen_address);
66
67 match tcp {
68 Ok(listener) => {
69 listen_connections(listener, paths);
70 }
71
72 Err(_) => {
73 eprintln!("Failed to listen stream");
74 }
75 }
76 }
77
78 pub fn listen_connections(listener: TcpListener, paths: Paths) {
79 let paths_lock = Arc::new(RwLock::new(paths));
80
81 for stream in listener.incoming() {
82 match stream {
83 Ok(stream) => {
84 let paths = Arc::clone(&paths_lock);
85
86 spawn(move || {
87 serve_client(stream, paths);
88 });
89 }
90
91 Err(error) => {
92 print!("Error receiving stream: {}", error);
93 }
94 }
95 }
96 }
97
98 pub struct Context {
99 pub accept_next: AtomicBool,
103 }
104
105 impl Context {
106 pub fn dont_wait(&self) {
107 self.accept_next.store(false, Ordering::Relaxed);
108 }
109 }
110
111 fn serve_client(stream: TcpStream, paths: Arc<RwLock<Paths>>) {
112 let context = Context {
113 accept_next: AtomicBool::new(true),
114 };
115
116 let context_ref = Arc::new(context);
117
118 while context_ref.accept_next.load(Ordering::Relaxed) {
119 let stream = stream.try_clone().expect("Error cloning stream");
120 decode_request(stream, paths.clone(), context_ref.clone());
121 }
122 }
123
124 pub fn decode_request(mut stream: TcpStream, paths: Arc<RwLock<Paths>>,
125 context: Arc<Context>) {
126 let mut header_start = String::new();
127 let mut partial_body_bytes = Vec::new();
128
129 const MAX_HEADER_SIZE: usize = 1024 * 1024; let headers_result = extract_headers(
131 &mut stream,
132 &mut header_start,
133 &mut partial_body_bytes,
134 MAX_HEADER_SIZE,
135 );
136
137 if !headers_result.is_ok() {
138 context.accept_next.store(false, Ordering::Relaxed);
139 return;
140 }
141
142 let headers = headers_result.unwrap();
143
144 let request_info = parse_request_method_header(&header_start.as_str());
145 if !request_info.is_some() {
146 context.accept_next.store(false, Ordering::Relaxed);
147 let _ = stream.shutdown(Shutdown::Both);
148 return;
149 }
150
151 let (method, raw_path) = request_info.unwrap();
152
153 let body_read = Arc::new(AtomicBool::from(false));
155 let body_parsed = Arc::new(AtomicBool::from(false));
156
157 let mut request = Request::new(context, stream, method, raw_path, headers,
158 body_read.clone(), body_parsed.clone());
159 request.setup();
160
161 request.set_partial_body_bytes(partial_body_bytes);
163
164 let mut matched_view: Option<&SinglePath> = None;
165
166 let binding = paths.read().unwrap();
167 for path in binding.iter() {
168 if request.pathname == path.name {
169 matched_view = Some(&path);
170 }
171 }
172
173 if let Some(view) = matched_view {
174 serve_page(request, view);
175 } else {
176 serve_not_found(request);
177 }
178 }
179
180 fn serve_page(request: Request, matched_path: &SinglePath) {
181 let response = Response::new(request.clone());
182 (matched_path.view)(request, response);
183 }
184
185 fn serve_not_found(request: Request) {
186 let mut response = Response::new(request);
187 response.html(404, "404 NOT FOUND".to_string());
188 response.send();
189 }
190}