From 39889425fb4f96aef011ec7b4cb7b7eb5085de76 Mon Sep 17 00:00:00 2001 From: Darius Auding <Darius.auding@gmx.de> Date: Fri, 9 Jun 2023 21:17:37 +0200 Subject: [PATCH] Working on new get post data function --- core/http/src/handling/request.rs | 327 ++++++++++++++++++------------ site/src/main.rs | 20 +- 2 files changed, 202 insertions(+), 145 deletions(-) diff --git a/core/http/src/handling/request.rs b/core/http/src/handling/request.rs index 09f5db6..8605de4 100644 --- a/core/http/src/handling/request.rs +++ b/core/http/src/handling/request.rs @@ -110,119 +110,176 @@ impl Request<'_> { } Ok(response) } - pub fn get_post_text_form_key( + + pub fn get_post_data( &self, keys: &[&str], data: &Data, - ) -> Result<HashMap<&str, Result<&str, ParseFormError>>, ParseFormError> { - let mut post_type = self + ) -> Result<HashMap<&str, Result<Vec<u8>, ParseFormError>>, ParseFormError> { + let mut post_type = if let Some(val) = self .headers .iter() .find(|header| header.contains("Content-Type: ")) - .unwrap() - .to_string(); - - post_type = post_type - .strip_prefix("Content-Type: ") - .unwrap() - .to_string(); - - let post_type: Vec<&str> = post_type.trim().split(';').collect(); - let mime_type = post_type[0].parse::<Mime>().unwrap(); - - let mut result = HashMap::new(); - match mime_type { - Mime::ApplicationXWwwFormUrlencoded => { - let data = String::from_utf8(data.buffer.clone()).unwrap(); - let kvps = data - .split("&") - .map(|kvp| kvp.split_once("=").unwrap()) - .collect::<HashMap<&str, &str>>(); - - for key in keys { - let entry = if let Some(val) = kvps.get(key) { - Ok(*val) - } else { - Err(ParseFormError { - error: ParseErrors::NoData, - }) - }; - result.insert(*key, entry); - } - Ok(result) + { + if let Ok(Type) = val.strip_prefix("Content-Type: ").unwrap().trim().parse() { + Type + } else { + return Err(ParseFormError { + error: ParseErrors::NoData, + }); } - Mime::MultipartFormData => { - let from_req = post_type[1..] - .iter() - .find(|val| val.contains("boundary=")) - .unwrap() - .strip_prefix("boundary=") - .unwrap(); - let mut boundary = b"--".to_vec(); - boundary.extend_from_slice(from_req.trim_matches('"').as_bytes()); - let mut end_boundary = boundary.clone(); - end_boundary.extend_from_slice(b"--"); - boundary.extend_from_slice(&[b'\r']); - let parts = data - .buffer - .split(|byte| byte == &b'\n') - .collect::<Vec<&[u8]>>(); + } else { + return Err(ParseFormError { + error: ParseErrors::NoData, + }); + }; - let mut boundary_found = false; - let mut current_key: Option<usize> = None; - let mut result: Vec<Vec<u8>> = vec!["".into(); keys.len()]; - for part in parts { - if part == [] { - continue; - } - if part == end_boundary { - break; - } - if !boundary_found && part == boundary { - current_key = None; - boundary_found = true; - continue; - } - if part.starts_with(b"Content-Disposition: form-data; name=") { - let headers = part - .split(|byte| byte == &b';') - .filter(|header| !header.is_empty()) - .collect::<Vec<_>>(); - if headers.len() < 2 { - continue; - } - let name = headers[1].split(|byte| byte == &b'=').collect::<Vec<_>>(); - if name.len() != 2 { - continue; - } - let mkey = String::from_utf8_lossy(name[1]) - .to_string() - .trim_end() - .trim_matches('"') - .to_owned(); - let mut index = 0; - for i in keys { - if *i == mkey { - current_key = Some(index); - } - index += 1; - } - boundary_found = false; - } else if let Some(key) = current_key { - result[key].extend_from_slice(part); - result[key].extend_from_slice(&[b'\n']); - } - } - Ok(result - .iter() - .map(|arr| String::from_utf8(arr.to_vec()).unwrap().trim().into()) - .collect()) - } + let data = data.buffer.as_slice(); + let mut keymap: HashMap<&str, Option<&[u8]>> = HashMap::with_capacity(keys.len()); + for i in keys { + keymap.entry(i).or_default(); + } + match post_type { + Mime::ApplicationXWwwFormUrlencoded => Ok(()), _ => Err(ParseFormError { error: ParseErrors::BadData, }), - } + }; + todo!() } + + // pub fn get_post_text_form_key( + // &self, + // keys: &[&str], + // data: &Data, + // ) -> Result<HashMap<&str, Result<&str, ParseFormError>>, ParseFormError> { + // let mut post_type = self + // .headers + // .iter() + // .find(|header| header.contains("Content-Type: ")) + // .unwrap() + // .to_string(); + // + // post_type = post_type + // .strip_prefix("Content-Type: ") + // .unwrap() + // .to_string(); + // + // let post_type: Vec<&str> = post_type.trim().split(';').collect(); + // let mime_type = post_type[0].parse().unwrap(); + // + // // let data = String::from_utf8(vec) + // + // let mut result = HashMap::new(); + // match mime_type { + // Mime::ApplicationXWwwFormUrlencoded => { + // let data = String::from_utf8(data.buffer.clone()).unwrap(); + // let kvps = data + // .split("&") + // .map(|kvp| kvp.split_once("=").unwrap()) + // .collect::<HashMap<&str, &str>>(); + // + // for key in keys { + // let entry = if let Some(val) = kvps.get(key) { + // Ok(*val) + // } else { + // Err(ParseFormError { + // error: ParseErrors::NoData, + // }) + // }; + // result.insert(*key, entry); + // } + // Ok(result) + // } + // Mime::MultipartFormData => { + // let from_req = post_type[1..] + // .iter() + // .find(|val| val.contains("boundary=")) + // .unwrap() + // .strip_prefix("boundary=") + // .unwrap(); + // let mut boundary = b"--".to_vec(); + // boundary.extend_from_slice(from_req.trim_matches('"').as_bytes()); + // let mut end_boundary = boundary.clone(); + // end_boundary.extend_from_slice(b"--"); + // boundary.extend_from_slice(&[b'\r']); + // let parts = data + // .buffer + // .split(|byte| byte == &b'\n') + // .collect::<Vec<&[u8]>>(); + // + // let mut boundary_found = false; + // let mut current_key: Option<&str> = None; + // let mut result: HashMap<&str, Vec<u8>> = HashMap::new(); + // for part in parts { + // if part == [] { + // continue; + // } + // if part == end_boundary { + // break; + // } + // if !boundary_found && part == boundary { + // current_key = None; + // boundary_found = true; + // continue; + // } + // if part.starts_with(b"Content-Disposition: form-data; name=") { + // let headers = part + // .split(|byte| byte == &b';') + // .filter(|header| !header.is_empty()) + // .collect::<Vec<_>>(); + // if headers.len() < 2 { + // continue; + // } + // let name = headers[1].split(|byte| byte == &b'=').collect::<Vec<_>>(); + // if name.len() != 2 { + // continue; + // } + // let mkey = String::from_utf8_lossy(name[1]) + // .as_ref() + // .trim_end() + // .trim_matches('"') + // .to_owned(); + // for i in keys { + // if *i == mkey { + // current_key = Some(&mkey); + // } + // } + // boundary_found = false; + // } else if let Some(key) = current_key { + // if None == result.get(key) { + // result.insert(key, part.to_vec()); + // continue; + // } + // result.get_mut(key).unwrap().extend_from_slice(part); + // } + // } + // if result.len() == 0 { + // return Err(ParseFormError { + // error: ParseErrors::NoData, + // }); + // } + // let return_result: HashMap<&str, Result<&str, ParseErrors>> = + // HashMap::with_capacity(keys.len()); + // + // for key in keys { + // let val = result.get(key).ok_or(ParseFormError { + // error: ParseErrors::NoData, + // }).map(|value| String::from_utf8(value)) + // let val = if let Ok(str) = String::from_utf8(val) { + // Ok(str) + // } else { + // Err(ParseFormError { + // error: ParseErrors::BadData, + // }) + // }; + // } + // } + // _ => Err(ParseFormError { + // error: ParseErrors::BadData, + // }), + // } + // } } #[cfg(test)] @@ -231,38 +288,38 @@ mod test { use super::Request; - #[test] - fn try_post_text() { - let req = Request { - uri: "", - headers: vec!["Content-Type: multipart/form-data;boundary=\"boundary\"".to_string()], - method: crate::handling::methods::Method::Post, - }; - let data = Data { - buffer: b"--boundary\r -Content-Disposition: form-data; name=\"field1\"\r -\r -value1\r ---boundary\r -Content-Disposition: form-data; name=\"field2\"; filename=\"example.txt\"\n\r -\r -value2\r ---boundary--" - .to_vec(), - is_complete: true, - }; - assert_eq!( - "value1", - req.get_post_text_form_key(&["field1"], &data).unwrap()[0] - ); - assert_eq!( - "value2", - req.get_post_text_form_key(&["field2"], &data).unwrap()[0] - ); - assert_eq!( - vec!["value1", "value2"], - req.get_post_text_form_key(&["field1", "field2"], &data) - .unwrap() - ) - } + // #[test] + // fn try_post_text() { + // let req = Request { + // uri: "", + // headers: vec!["Content-Type: multipart/form-data;boundary=\"boundary\"".to_string()], + // method: crate::handling::methods::Method::Post, + // }; + // let data = Data { + // buffer: b"--boundary\r + // Content-Disposition: form-data; name=\"field1\"\r + // \r + // value1\r + // --boundary\r + // Content-Disposition: form-data; name=\"field2\"; filename=\"example.txt\"\n\r + // \r + // value2\r + // --boundary--" + // .to_vec(), + // is_complete: true, + // }; + // assert_eq!( + // "value1", + // req.get_post_text_form_key(&["field1"], &data).unwrap()[0] + // ); + // assert_eq!( + // "value2", + // req.get_post_text_form_key(&["field2"], &data).unwrap()[0] + // ); + // assert_eq!( + // vec!["value1", "value2"], + // req.get_post_text_form_key(&["field1", "field2"], &data) + // .unwrap() + // ) + // } } diff --git a/site/src/main.rs b/site/src/main.rs index 1005312..2a16f43 100644 --- a/site/src/main.rs +++ b/site/src/main.rs @@ -3,17 +3,17 @@ use std::{collections::HashMap, path::PathBuf}; use http::handling::{ file_handlers::NamedFile, methods::Method, - request::Request, + request::{Request, ParseFormError}, response::{Outcome, Response, ResponseBody, Status}, routes::{Data, Route}, }; -fn hashmap_to_string(map: &HashMap<&str, &str>) -> String { +fn hashmap_to_string(map: &HashMap<&str, Result<&str, ParseFormError>>) -> String { let mut result = String::new(); for (key, value) in map { result.push_str(key); result.push('='); - result.push_str(value); + result.push_str(value.as_ref().unwrap()); result.push(';'); } result.pop(); // Remove the trailing semicolon if desired @@ -21,7 +21,7 @@ fn hashmap_to_string(map: &HashMap<&str, &str>) -> String { } fn handle_static_hi(request: Request<'_>, data: Data) -> Outcome<Response, Status, Data> { - let keys = if let Ok(keys) = request.get_get_form_keys(vec!["asdf", "jkl"]) { + let keys = if let Ok(keys) = request.get_get_form_keys(&["asdf", "jkl"]) { keys } else { return Outcome::Forward(data); @@ -62,12 +62,12 @@ fn post_hi_handler(request: Request, data: Data) -> Outcome<Response, Status, Da if data.is_empty() { return Outcome::Forward(data); } - let data = if let Ok(val) = request.get_post_text_form_key("message", &data) { - val - } else { - return Outcome::Failure(Status::BadRequest); - }; - let dat = post_hi(data); + // let data = if let Ok(val) = request.get_post_text_form_key("message", &data) { + // val + // } else { + // return Outcome::Failure(Status::BadRequest); + // }; + let dat = post_hi(String::from_utf8(data.buffer).unwrap()); Outcome::Success(Response { headers: vec![ format!("Content-Length: {}", dat.len()), -- GitLab