Add Getting files from the server

Change-Id: I48f56a1291934742ae905416ce455f50123439f0
Reviewed-on: https://git.clicks.codes/c/Clicks/BYO/HttpServer/rust/+/261
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 6320bd7..90cc586 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,11 +1,17 @@
-use std::{io::Result, collections::HashMap};
-use tokio::{net::{TcpListener, TcpStream}, io::{AsyncReadExt, AsyncWriteExt}};
+use std::{io, collections::HashMap, env::args, os::unix::fs::MetadataExt};
+use bytes::BytesMut;
+use tokio::{net::{TcpListener, TcpStream}, io::{AsyncReadExt, AsyncWriteExt}, fs::File};
 
 
 use itertools::Itertools;
 use nom::AsChar;
 
-async fn process_socket(mut stream: TcpStream) {
+enum BodyTypes {
+    File(File),
+    String(String)
+}
+
+async fn process_socket(mut stream: TcpStream) -> Result<(), &'static str> {
     println!("accepted new connection");
 
     let mut request: HashMap<String, String> = HashMap::new();
@@ -46,7 +52,7 @@
 
     let response_status: String;
     let mut response_headers: Vec<String> = vec![];
-    let response_body: String;
+    let response_body: BodyTypes;
 
     // println!("{:?}", path);
 
@@ -55,34 +61,82 @@
     match path.next().unwrap() {
         "" => {
             response_status = "200 OK".into();
-            response_body = "".into();
+            response_body = BodyTypes::String("".into());
         },
         "echo" => {
             response_status = "200 OK".into();
-            response_body = path.join("/");
+            response_body = BodyTypes::String(path.join("/"));
             response_headers.push("Content-Type: text/plain".into());
         },
         "user-agent" => {
             response_status = "200 OK".into();
-            response_body = request.get("User-Agent").unwrap().into();
+            response_body = BodyTypes::String(request.get("User-Agent").unwrap().into());
             response_headers.push("Content-Type: text/plain".into());
         },
+        "files" => {
+            let file_name = path.join("/");
+            let args: Vec<String> = args().collect();
+            let file_path = if &args[1] == "directory" {
+                args[2].to_owned() + file_name.as_str()
+            } else {
+                return Err("No directory Given".into())
+            };
+            let maybe_file = File::open(file_path).await;
+
+            match maybe_file {
+                Ok(file) => {
+                    response_status = "200 OK".into();
+                    response_body = BodyTypes::File(file);
+                },
+                Err(_) => {
+                    response_status = "404 Not Found".into();
+                    response_body = BodyTypes::String("".into());
+                }
+            }
+        },
         _ => {
             response_status = "404 Not Found".into();
-            response_body = "".into();
+            response_body = BodyTypes::String("".into());
         }
     }
 
-    if response_body.len() > 0 {
-        response_headers.push(format!("Content-Length: {}", response_body.len()));
+    match response_body {
+        BodyTypes::String(ref content) => {
+            if content.len() > 0 {
+                response_headers.push(format!("Content-Length: {}", content.len()));
+            };
+        },
+        BodyTypes::File(ref file) => {
+            response_headers.push(format!("Content-Length: {}", file.metadata().await.unwrap().size()));
+        }
     }
 
-    stream.write(format!("HTTP/1.1 {response_status}\r\n{}\r\n\r\n{response_body}", response_headers.join("\r\n")).as_bytes()).await.unwrap();
+    stream.write(format!("HTTP/1.1 {response_status}\r\n{}\r\n\r\n", response_headers.join("\r\n")).as_bytes()).await.unwrap();
 
+    match response_body {
+        BodyTypes::String(ref content) => {
+            stream.write(content.as_bytes()).await.unwrap();
+        },
+        BodyTypes::File(mut file) => {
+            loop {
+                let mut buf = BytesMut::with_capacity(1024);
+
+                let read = file.read_buf(&mut buf).await.unwrap();
+
+                if read == 0 {
+                    break;
+                }
+
+                stream.write(&mut buf).await.unwrap();
+            }
+        }
+    }
+
+    Ok(())
 }
 
 #[tokio::main]
-async fn main() -> Result<()> {
+async fn main() -> io::Result<()> {
     let listener = TcpListener::bind("127.0.0.1:4221").await?;
     let mut futures = vec![];