Add User-Agent Path, Parse request through
 User-Agent Header

Change-Id: I4c08eebe773beac21a96873b208e13b3a904a74b
Reviewed-on: https://git.clicks.codes/c/Clicks/BYO/HttpServer/rust/+/252
Tested-by: Skyler Grey <minion@clicks.codes>
Reviewed-by: Samuel Shuert <coded@clicks.codes>
diff --git a/src/main.rs b/src/main.rs
index 26d1433..7ba1722 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,6 +1,7 @@
-use std::{net::TcpListener, io::{Write, Read}};
+use std::{net::TcpListener, io::{Write, Read}, collections::HashMap};
 
 use itertools::Itertools;
+use nom::AsChar;
 
 fn main() {
     let listener = TcpListener::bind("127.0.0.1:4221").unwrap();
@@ -10,27 +11,39 @@
             Ok(mut _stream) => {
                 println!("accepted new connection");
 
-                let mut request: Vec<Vec<char>> = vec![vec![]];
-                let mut part: usize = 0;
-
+                let mut request: HashMap<String, String> = HashMap::new();
+                let mut line_num: usize = 0;
                 loop {
-                    let mut buf: [u8; 1] = [0; 1];
-                    _stream.read_exact(&mut buf).unwrap();
+                    let mut line = String::default();
 
-                    if buf[0] == b' ' {
-                        part += 1;
-                        request.push(vec![]);
+                    loop {
+                        let mut buf: [u8; 1] = [0; 1];
+                        _stream.read_exact(&mut buf).unwrap();
+
+                        let character = buf[0].as_char();
+                        if character == '\n' {
+                            break
+                        } else if character != '\r' {
+                            line.push(character);
+                        }
+                    }
+
+                    if line_num == 0 {
+                        let mut splits = line.split(' ');
+                        request.insert("method".to_owned(), splits.next().unwrap().to_owned());
+                        request.insert("path".to_owned(), splits.next().unwrap().to_owned());
                     } else {
-                        request[part].push(buf[0].into());
+                        let mut splits = line.split(':');
+                        let key = splits.next().unwrap();
+                        let value = splits.next().unwrap();
+                        request.insert(key.to_owned(), value.to_owned());
                     }
 
-                    if part == 2 {
-                        break;
-                    }
+                    if request.contains_key("User-Agent") { break };
+                    line_num += 1;
                 }
 
-                let unparsed_path = request[1].iter().collect::<String>();
-                let mut path = unparsed_path.split("/");
+                let mut path = request.get("path").unwrap().split("/");
 
                 let response_status: String;
                 let mut response_headers: Vec<String> = vec![];
@@ -38,28 +51,39 @@
 
                 // println!("{:?}", path);
 
-                // println!("{:?}", path);
-
                 path.next().unwrap();
 
                 match path.next().unwrap() {
                     "" => {
-                        response_status = "200 OK".to_owned();
-                        response_body = "".to_owned();
+                        response_status = "200 OK".into();
+                        response_body = "".into();
                     },
                     "echo" => {
-                        response_status = "200 OK".to_owned();
+                        response_status = "200 OK".into();
                         response_body = path.join("/");
-                        response_headers.push("Content-Type: text/plain".to_owned());
-                        response_headers.push(format!("Content-Length: {}", response_body.len()));
+                        response_headers.push("Content-Type: text/plain".into());
+                        
+                    },
+                    "user-agent" => {
+                        response_status = "200 OK".into();
+                        response_body = request.get("User-Agent").unwrap().into();
+                        response_headers.push("Content-Type: text/plain".into());
                     },
                     _ => {
-                        response_status = "404 Not Found".to_owned();
-                        response_body = "".to_owned();
+                        response_status = "404 Not Found".into();
+                        response_body = "".into();
                     }
                 }
 
-                _stream.write(format!("HTTP/1.1 {response_status}\r\n{}\r\n\r\n{response_body}\r\n", response_headers.join("\r\n")).as_bytes()).unwrap();
+                let eor: Option<&str>;
+                if response_body.len() > 0 {
+                    response_headers.push(format!("Content-Length: {}", response_body.len()));
+                    eor = Some("\r\n");
+                } else {
+                    eor = None;
+                }
+
+                _stream.write(format!("HTTP/1.1 {response_status}\r\n\r\n{}\r\n{response_body}{}", response_headers.join("\r\n"), eor.unwrap_or_default()).as_bytes()).unwrap();
             }
             Err(e) => {
                 println!("error: {}", e);