Check for mime-type and JS fun

This commit is contained in:
2025-03-20 10:54:54 +01:00
parent 704a03be3d
commit a9185aa868
5 changed files with 121 additions and 84 deletions

23
Cargo.lock generated
View File

@ -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"

View File

@ -5,3 +5,4 @@ edition = "2021"
[dependencies]
signal-hook = "0.3.17"
mime_guess = "2.0.5"

View File

@ -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<Vec<u8>, Box<dyn Error>> {
let mut response_field_lines: HashMap<String, String> = HashMap::new();
let mut response_body: Vec<u8> = vec![];
let response: Vec<u8>;
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<dyn Error>> {
let mut line = String::new();
let mut reader = BufReader::new(&mut stream);
@ -384,85 +460,9 @@ fn handle_request(mut stream: TcpStream) -> Result<(), Box<dyn Error>> {
// reader.read_to_end(&mut body)?;
// dbg!(&body);
let mut response_field_lines: HashMap<String, String> = HashMap::new();
let mut response_body: Vec<u8> = 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(())
}

View File

@ -3,8 +3,12 @@
<head>
<meta charset="utf-8">
<title>http-server</title>
<script src="main.js" async></script>
</head>
<body>
<h1>Hello, World!</h1>
<button type="button" id="click-me">Click Me!</button>
<div id="output"></div>
</body>
</html>

9
www/main.js Normal file
View File

@ -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.";
}
});