use std::collections::HashMap;
use crate::enums::Method;
#[derive(Debug)]
pub struct Request {
pub method: Method,
pub url: String,
pub(crate) version: String,
pub headers: HashMap<String, String>,
pub params: HashMap<String, String>
}
impl Request {
pub fn new(buffer: Vec<u8>) -> Result<Self,()> {
let buffer_string = Self::parse_buffer(buffer);
let (method, url, version, headers) = Self::parse_buffer_string(buffer_string)?;
Ok(Self {
method,
url,
version,
headers,
params: HashMap::new(),
})
}
fn parse_buffer(buffer: Vec<u8>) -> String{
let string = String::from_utf8(buffer).expect("Received string is not UTF-8 ( Unable to parse stream )");
string
}
fn parse_buffer_string(buffer_string: String) -> Result<(Method, String, String, HashMap<String, String>), ()>{
if !buffer_string.is_empty(){
let mut splitted_buffer_string = buffer_string.split("\r\n\r\n");
match splitted_buffer_string.next(){
Some(header_string) => {
let (method, url, version, headers) = Self::parse_header_string(header_string);
return Ok((method, url, version, headers));
},
None => (),
}
}
Err(())
}
fn parse_header_string(header_string: &str) -> (Method, String, String, HashMap<String, String>){
let mut splitted_header_string = header_string.split("\r\n");
let (method, url, version) = match splitted_header_string.next(){
Some(meta_string) => {
Self::parse_meta_string(meta_string)
},
None => panic!("Unable to fetch meta values"),
};
let mut headers: HashMap<String, String> = HashMap::new();
for header in splitted_header_string{
if !header.is_empty(){
let header = Self::parse_header(header);
match header{
Ok((key, value)) => {
headers.insert(key, value);
},
Err(_) => break,
}
}
}
(method, url, version, headers)
}
fn parse_meta_string(meta_string: &str) -> (Method, String, String){
let mut splitted_meta_string = meta_string.split(" ");
let method = match splitted_meta_string.next(){
Some(method) => Method::parse(method.trim()),
None => panic!("Unable to fetch method"),
};
let url = match splitted_meta_string.next(){
Some(url) => url.trim().to_string(),
None => panic!("Unable to fetch url"),
};
let version = match splitted_meta_string.next(){
Some(version) => version.trim().to_string(),
None => panic!("Unable to fetch version"),
};
(method, url, version)
}
fn parse_header(header_string: &str) -> Result<(String, String), ()> {
let mut key_value_string = header_string.split(":");
let key = match key_value_string.next() {
Some(key) => key.trim().to_string(),
None => return Err(()),
};
let value = match key_value_string.next() {
Some(value) => value.trim().to_string(),
None => return Err(()),
};
Ok((key, value))
}
}