use std::collections::HashMap; use std::fmt; use crate::http_method::HttpMethod; pub struct Request { pub method: HttpMethod, path: String, http_version: String, headers: HashMap, body: Vec, } impl Request { pub fn new( method: HttpMethod , path: String , http_version: String , headers: HashMap , body: Vec ) -> Request { return Request { method, path, http_version, headers, body, }; } // TODO(andrew): add some error handling. pub fn from(data: &[u8]) -> Option { let mut lines: Vec = Vec::new(); let mut line = String::new(); let mut idx = 0; let mut char_count = 0; // Parsing headers until first empty line (char_count == 0). for c in data { let c = *c as char; line.push(c); idx += 1; if c == '\n' { lines.push(line); if char_count == 0 { break; } else { line = String::new(); } } if c != '\r' && c != '\n' { char_count += 1; } } let body = data[idx..].to_vec(); let mut headers: HashMap = HashMap::new(); for line in &lines[1..] { let line = line .trim_end_matches("\r\n") .split(": ") .collect::>(); headers.insert(String::from(line[0]), line[1..].join(" ")); } let first_line = lines[0] .trim_end_matches("\r\n") .split(" ") .collect::>(); let method = String::from(first_line[0]); match HttpMethod::parse(method) { Some(method) => return Some(Request::new( method, String::from(first_line[1]), String::from(first_line[2]), headers, body )), None => return None }; } } impl fmt::Display for Request { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { return write!(f, "Request({}, {})", self.method, self.path); } }