From a9185aa86878ae1099dac320aa195607f4bf219d Mon Sep 17 00:00:00 2001 From: AustrianToast Date: Thu, 20 Mar 2025 10:54:54 +0100 Subject: [PATCH] Check for mime-type and JS fun --- Cargo.lock | 23 +++++++ Cargo.toml | 1 + src/main.rs | 168 ++++++++++++++++++++++++------------------------- www/index.html | 4 ++ www/main.js | 9 +++ 5 files changed, 121 insertions(+), 84 deletions(-) create mode 100644 www/main.js diff --git a/Cargo.lock b/Cargo.lock index 605e00f..de14aaf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,6 +6,7 @@ version = 4 name = "http_server" version = "0.1.0" dependencies = [ + "mime_guess", "signal-hook", ] @@ -15,6 +16,22 @@ version = "0.2.171" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "signal-hook" version = "0.3.17" @@ -33,3 +50,9 @@ checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] + +[[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" diff --git a/Cargo.toml b/Cargo.toml index afbb461..1ae8bc1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,3 +5,4 @@ edition = "2021" [dependencies] signal-hook = "0.3.17" +mime_guess = "2.0.5" diff --git a/src/main.rs b/src/main.rs index cc52dad..932f5bf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,7 @@ use std::{ thread, }; -#[derive(PartialEq, Eq, Debug)] +#[derive(PartialEq, Eq, Debug, Copy, Clone)] enum RequestMethods { NULL = -1, // This is only to initialise the struct GET, @@ -40,11 +40,7 @@ impl RequestLine { } // Only GET and HEAD are required, the rest is optional - if ["GET", "HEAD"].contains(&method.trim()) { - return true; - } else { - return false; - } + ["GET", "HEAD"].contains(&method.trim()) } // TODO: make the checks less shit and actually correct @@ -350,6 +346,86 @@ fn response_builder( return response; } +fn act_upon_request(start_line: &RequestLine) -> Result, Box> { + let mut response_field_lines: HashMap = HashMap::new(); + let mut response_body: Vec = vec![]; + let response: Vec; + + if start_line.target == "/" { + let file = match fs::read("./www/index.html") { + Ok(val) => val, + Err(_) => { + b"The is no index.html, only you and me." + .iter() + .for_each(|byte| response_body.push(*byte)); + + response_field_lines.insert( + String::from("Content-Length"), + response_body.len().to_string(), + ); + response_field_lines + .insert(String::from("Content-Type"), String::from("text/plain")); + + response = response_builder( + start_line.method, + "HTTP/1.1 200 OK", + response_field_lines, + Some(response_body), + ); + + return Ok(response); + } + }; + + file.iter().for_each(|byte| response_body.push(*byte)); + + response_field_lines.insert(String::from("Content-Length"), file.len().to_string()); + response_field_lines.insert(String::from("Content-Type"), String::from("text/html")); + + response = response_builder( + start_line.method, + "HTTP/1.1 200 OK", + response_field_lines, + Some(response_body), + ); + } else { + let path: PathBuf = PathBuf::from(format!("./www{}", start_line.target)); + + match fs::read(&path) { + Ok(val) => { + val.iter().for_each(|byte| response_body.push(*byte)); + + response_field_lines.insert( + String::from("Content-Length"), + response_body.len().to_string(), + ); + // TODO: get mime-type of file and use that here + let mime_type = mime_guess::from_path(&path) + .first_raw() + .expect("Could not guess mime-type from path"); + response_field_lines.insert(String::from("Content-Type"), mime_type.to_string()); + + response = response_builder( + start_line.method, + "HTTP/1.1 200 OK", + response_field_lines, + Some(response_body), + ); + } + Err(_) => { + response = response_builder( + start_line.method, + "HTTP/1.1 404 Not Found", + response_field_lines, + None, + ); + } + }; + } + + Ok(response) +} + fn handle_request(mut stream: TcpStream) -> Result<(), Box> { let mut line = String::new(); let mut reader = BufReader::new(&mut stream); @@ -384,85 +460,9 @@ fn handle_request(mut stream: TcpStream) -> Result<(), Box> { // reader.read_to_end(&mut body)?; // dbg!(&body); - let mut response_field_lines: HashMap = HashMap::new(); - let mut response_body: Vec = vec![]; - // TODO: Act upon the request - if start_line.target == "/" { - let file = match fs::read("./www/index.html") { - Ok(val) => val, - Err(_) => { - b"The is no index.html, only you and me." - .iter() - .for_each(|byte| response_body.push(*byte)); - - response_field_lines.insert( - String::from("Content-Length"), - response_body.len().to_string(), - ); - response_field_lines - .insert(String::from("Content-Type"), String::from("text/plain")); - - let response = response_builder( - start_line.method, - "HTTP/1.1 200 OK", - response_field_lines, - Some(response_body), - ); - - stream.write_all(&response)?; - return Ok(()); - } - }; - - file.iter().for_each(|byte| response_body.push(*byte)); - - response_field_lines.insert(String::from("Content-Length"), file.len().to_string()); - response_field_lines.insert(String::from("Content-Type"), String::from("text/html")); - - let response = response_builder( - start_line.method, - "HTTP/1.1 200 OK", - response_field_lines, - Some(response_body), - ); - - stream.write_all(&response)?; - } else { - let path: PathBuf = PathBuf::from(format!("./www{}", start_line.target)); - - match fs::read(path) { - Ok(val) => { - val.iter().for_each(|byte| response_body.push(*byte)); - - response_field_lines.insert( - String::from("Content-Length"), - response_body.len().to_string(), - ); - // TODO: get mime-type of file and use that here - response_field_lines.insert(String::from("Content-Type"), String::from("*/*")); - - let response = response_builder( - start_line.method, - "HTTP/1.1 200 OK", - response_field_lines, - Some(response_body), - ); - - stream.write_all(&response)?; - } - Err(_) => { - let response = response_builder( - start_line.method, - "HTTP/1.1 404 Not Found", - response_field_lines, - None, - ); - - stream.write_all(&response)?; - } - }; - } + let response = act_upon_request(&start_line)?; + stream.write_all(&response)?; Ok(()) } diff --git a/www/index.html b/www/index.html index afc9179..ccc9acb 100644 --- a/www/index.html +++ b/www/index.html @@ -3,8 +3,12 @@ http-server +

Hello, World!

+ + +
diff --git a/www/main.js b/www/main.js new file mode 100644 index 0000000..fb368ab --- /dev/null +++ b/www/main.js @@ -0,0 +1,9 @@ +document.getElementById("click-me").addEventListener("click", function() { + let output = document.getElementById("output"); + + if (output.innerHTML != "") { + output.innerHTML = "" + } else { + document.getElementById("output").innerHTML = "Wow! This actually works."; + } +});