diff --git a/core/http/src/handlers/handlers.rs b/core/http/src/handlers/handlers.rs index 0cf7d481fc457bee4097495bac842ea52ad6eeb4..d9ba8df51bca6645819fd56caae79decabfeac6c 100755 --- a/core/http/src/handlers/handlers.rs +++ b/core/http/src/handlers/handlers.rs @@ -15,29 +15,45 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin let mut http_request: Vec<String> = Vec::with_capacity(100); loop { let mut buffer = String::new(); - let _ = buf_reader.read_line(&mut buffer).await.unwrap(); + if let Err(_) = buf_reader.read_line(&mut buffer).await { + eprintln!("\x1b[31mAborting due to invalid UTF-8 in request header\x1b[0m"); + return; + } if buffer == "\r\n" { break; } http_request.push(buffer); } - println!("{:#?}", http_request); + // println!("{:#?}", http_request); - let request_status_line = http_request.get(0); - if request_status_line == None { + let request_status_line = if let Some(status_line) = http_request.get(0).cloned() { + status_line + } else { + eprintln!("\x1b[31mAborting due to missing headers\x1b[0m"); return; - } - let request_status_line = request_status_line.unwrap(); + }; let request = Request { - uri: &request_status_line.split(" ").nth(1).unwrap(), - headers: http_request.clone(), - method: request_status_line + uri: if let Some(uri) = &request_status_line.split(" ").nth(1) { + *uri + } else { + eprintln!("\x1b[31mAborting due to invalid status line\x1b[0m"); + return; + }, + headers: http_request, + method: if let Some(method) = request_status_line .split(" ") - .next() - .unwrap() - .parse() - .unwrap(), + .next() { + if let Ok(ok) = method.parse() { + ok + } else { + eprintln!("\x1b[31mAborting due to invalid request method\x1b[0m"); + return; + } + } else { + eprintln!("\x1b[31mAborting due to invalid status line\x1b[0m"); + return; + } }; let mut data = Data { @@ -48,8 +64,7 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin let length = if let Some(len) = request .headers .iter() - .filter(|header| header.contains("Content-Length: ")) - .clone() + .filter(|header| header.starts_with("Content-Length: ")) .map(|header| { let header = header.strip_prefix("Content-Length: ").unwrap(); header.trim().parse::<usize>() @@ -64,12 +79,17 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin } else { 0 }; + let mut buffer: Vec<u8> = vec![]; buf_reader.read_buf(&mut buffer).await.unwrap(); if buffer.len() != length { - let respone = len_not_defined(Status::LengthRequired).await; - stream.write_all(respone.0.as_bytes()).await.unwrap(); - stream.write(&respone.1).await.unwrap(); + let respone = len_not_defined(Status::LengthRequired); + let mut response = respone.0.as_bytes().to_vec(); + response.extend_from_slice(&respone.1); + if let Err(e) = stream.write_all(&response).await { + eprintln!("\x1b[31mError {e} occured when trying to write answer to TCP-Stream for Client, aborting\x1b[0m"); + return; + } return; } data.is_complete = true; @@ -107,22 +127,27 @@ pub async fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoin let response = match handled_response { Some(val) => match val { Outcome::Success(success) => ( - format!("HTTP/1.1 {}\r\n", success.status.unwrap()) + format!("HTTP/1.1 {}\r\n", success.status.unwrap_or(Status::Ok)) + &success.headers.join("\r\n") + "\r\n\r\n", success.body.get_data(), ), - Outcome::Failure(error) => failure_handler(error).await, - Outcome::Forward(_) => failure_handler(Status::NotFound).await, + Outcome::Failure(error) => failure_handler(error), + Outcome::Forward(_) => failure_handler(Status::NotFound), }, - None => failure_handler(Status::NotFound).await, + None => failure_handler(Status::NotFound), }; - stream.write_all(response.0.as_bytes()).await.unwrap(); - stream.write(&response.1).await.unwrap(); + let mut resp = response.0.as_bytes().to_vec(); + resp.extend_from_slice(&response.1); + if let Err(e) = stream.write_all(&resp).await { + eprintln!("\x1b[31mError {e} occured when trying to write answer to TCP-Stream for Client, aborting\x1b[0m"); + return; + } + return; } -async fn failure_handler(status: Status) -> (String, Vec<u8>) { +fn failure_handler(status: Status) -> (String, Vec<u8>) { let page_404 = NamedFile::open(PathBuf::from("404.html")).unwrap(); ( format!( @@ -135,7 +160,7 @@ async fn failure_handler(status: Status) -> (String, Vec<u8>) { ) } -async fn len_not_defined(status: Status) -> (String, Vec<u8>) { +fn len_not_defined(status: Status) -> (String, Vec<u8>) { let page_411 = NamedFile::open(PathBuf::from("411.html")).unwrap(); ( format!( diff --git a/core/http/src/handling/request.rs b/core/http/src/handling/request.rs index b3615f15db22cc3a11631ad7ce585274ccdae22c..7fa10b44a2c46fc29122a9f7290de8d95e3004a9 100644 --- a/core/http/src/handling/request.rs +++ b/core/http/src/handling/request.rs @@ -64,14 +64,14 @@ impl Request<'_> { } } pub fn get_form_keys(&self, keys: Vec<&str>) -> Result<HashMap<&str, &str>, ParseFormError> { - let data = self.uri.split_once("?"); - if data == None { + let data = if let Some(val) = self.uri.split_once("?") { + val + } else { return Err(ParseFormError { error: ParseErrors::NoData, }); - } + }; let data = data - .unwrap() .1 .split("&") .map(|kvp| kvp.split_once("=")) @@ -79,21 +79,23 @@ impl Request<'_> { let mut values: HashMap<&str, &str> = HashMap::new(); for kvp in data { - if kvp == None { + let kvp = if let Some(kvp) = kvp { + kvp + } else { continue; - } - let kvp = kvp.unwrap(); + }; values.insert(kvp.0, kvp.1); } let mut response = HashMap::new(); for key in keys { - let entry = values.get_key_value(key); - if entry == None { + let entry = if let Some(val) = values.get_key_value(key) { + val + } else { return Err(ParseFormError { error: ParseErrors::NoData, }); - } - response.insert(*entry.unwrap().0, *entry.unwrap().1); + }; + response.insert(*entry.0, *entry.1); } Ok(response) } diff --git a/core/http/src/handling/routes.rs b/core/http/src/handling/routes.rs index 795e760f90cd3a64934e1e222b301f1afee9a031..9ded1ced3026c6bfa96ea4cb249a57603962c17a 100644 --- a/core/http/src/handling/routes.rs +++ b/core/http/src/handling/routes.rs @@ -35,7 +35,7 @@ impl Route<'_> { format: routeinfo.format, } } - pub fn compare_uri(self, uri: Uri) -> bool { + pub fn compare_uri(&self, uri: Uri) -> bool { let mut iter_comp_str = uri.split("/"); for true_str in self.uri.split("/") { let comp_str = if let Some(str) = iter_comp_str.next() { diff --git a/core/http/src/setup.rs b/core/http/src/setup.rs index a50e7d1caf4a052c6f5648ca445e0ff6cb8368f3..9f57e76f3f1d617f809960ce966887e063ce21a3 100644 --- a/core/http/src/setup.rs +++ b/core/http/src/setup.rs @@ -19,7 +19,22 @@ pub struct Config { } impl<'a> Config { - pub fn mount(mut self, mountpoint: Uri<'static>, mut routes: Vec<Route<'static>>) -> Config { + fn check_mountpoint_taken(&self, to_insert: Uri) -> bool { + if let Some(to_check) = &self.mountpoints { + let len = to_check.len(); + for i in 0..len { + if to_check[i].mountpoint == to_insert { + return true; // Found a duplicate &str + } + } + }; + false + } + pub fn mount(mut self, mountpoint: Uri<'static>, mut routes: Vec<Route<'static>>) -> Self { + if self.check_mountpoint_taken(mountpoint) { + eprintln!("\x1b[31mTrying to reassign a mountpoint, mountpoint `{mountpoint}` already taken.\x1b[0m"); + return self; + } routes.sort_by(|a, b| a.rank.cmp(&b.rank)); let mut mount_message = format!(" >> \x1b[35m{}\x1b[0m\n", mountpoint); for (index, route) in routes.iter().enumerate() { @@ -58,10 +73,7 @@ impl<'a> Config { println!("Shutting down..."); break; } - - income = self.address.accept() => { - let income = income.unwrap(); - let (socket, _) = income; + Ok((socket, _)) = self.address.accept() => { let mountpoints = self.mountpoints.clone().unwrap(); tokio::spawn(async move { handle_connection(socket, mountpoints).await; }); } @@ -70,7 +82,11 @@ impl<'a> Config { } } pub async fn build(ip: &str) -> Config { - let listener = TcpListener::bind(ip).await.unwrap(); + let listener = if let Ok(listener) = TcpListener::bind(ip).await { + listener + } else { + panic!("\x1b[31mCould't bind Listener to address\x1b[0m"); + }; let ip = ip.splitn(2, ":").collect::<Vec<&str>>(); if ip.len() != 2 { panic!("Invalid IP Address"); diff --git a/site/src/main.rs b/site/src/main.rs index 22897e249dc9114d5d0a239d9f281bdf663dee8f..48d109dd82b347301653cef35697c49db3bdd9b0 100644 --- a/site/src/main.rs +++ b/site/src/main.rs @@ -1,4 +1,4 @@ -use std::{path::PathBuf, collections::HashMap}; +use std::{collections::HashMap, path::PathBuf}; use http::handling::{ file_handlers::NamedFile, @@ -20,17 +20,19 @@ fn hashmap_to_string(map: &HashMap<&str, &str>) -> String { result } - fn handle_static_hi(request: Request<'_>, _data: Data) -> Outcome<Response, Status, Data> { let response = hashmap_to_string(&request.get_form_keys(vec!["asdf", "jkj"]).unwrap()); - Outcome::Success(Response { headers: vec![ - format!("Content-Length: {}", response.len()), - format!("Content-Type: text/plain") - ], status: Some(Status::Ok), body: Box::new(response) }) + Outcome::Success(Response { + headers: vec![ + format!("Content-Length: {}", response.len()), + format!("Content-Type: text/plain"), + ], + status: Some(Status::Ok), + body: Box::new(response), + }) // Outcome::Forward(data) } - fn handler(request: Request<'_>, _data: Data) -> Outcome<Response, Status, Data> { let response = fileserver(request.uri.strip_prefix("static/").unwrap()); let response = match response { @@ -96,15 +98,18 @@ async fn main() { }; let static_hi = Route { - format: None, + format: None, handler: handle_static_hi, name: Some("Handle_Static_hi"), uri: "static/hi", method: Method::Get, - rank: 0 + rank: 0, }; - http::build("127.0.0.1:8000").await + http::build("127.0.0.1:8000") + .await .mount("/", vec![fileserver, post_test, static_hi]) - .launch().await; + .mount("/post/", vec![post_test]) + .launch() + .await; }