Check for mime-type and JS fun
This commit is contained in:
23
Cargo.lock
generated
23
Cargo.lock
generated
@ -6,6 +6,7 @@ version = 4
|
|||||||
name = "http_server"
|
name = "http_server"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"mime_guess",
|
||||||
"signal-hook",
|
"signal-hook",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -15,6 +16,22 @@ version = "0.2.171"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
|
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]]
|
[[package]]
|
||||||
name = "signal-hook"
|
name = "signal-hook"
|
||||||
version = "0.3.17"
|
version = "0.3.17"
|
||||||
@ -33,3 +50,9 @@ checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicase"
|
||||||
|
version = "2.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
|
||||||
|
@ -5,3 +5,4 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
signal-hook = "0.3.17"
|
signal-hook = "0.3.17"
|
||||||
|
mime_guess = "2.0.5"
|
||||||
|
166
src/main.rs
166
src/main.rs
@ -10,7 +10,7 @@ use std::{
|
|||||||
thread,
|
thread,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Debug)]
|
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
|
||||||
enum RequestMethods {
|
enum RequestMethods {
|
||||||
NULL = -1, // This is only to initialise the struct
|
NULL = -1, // This is only to initialise the struct
|
||||||
GET,
|
GET,
|
||||||
@ -40,11 +40,7 @@ impl RequestLine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only GET and HEAD are required, the rest is optional
|
// Only GET and HEAD are required, the rest is optional
|
||||||
if ["GET", "HEAD"].contains(&method.trim()) {
|
["GET", "HEAD"].contains(&method.trim())
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: make the checks less shit and actually correct
|
// TODO: make the checks less shit and actually correct
|
||||||
@ -350,6 +346,86 @@ fn response_builder(
|
|||||||
return response;
|
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>> {
|
fn handle_request(mut stream: TcpStream) -> Result<(), Box<dyn Error>> {
|
||||||
let mut line = String::new();
|
let mut line = String::new();
|
||||||
let mut reader = BufReader::new(&mut stream);
|
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)?;
|
// reader.read_to_end(&mut body)?;
|
||||||
// dbg!(&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
|
// TODO: Act upon the request
|
||||||
if start_line.target == "/" {
|
let response = act_upon_request(&start_line)?;
|
||||||
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)?;
|
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)?;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,12 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>http-server</title>
|
<title>http-server</title>
|
||||||
|
<script src="main.js" async></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>Hello, World!</h1>
|
<h1>Hello, World!</h1>
|
||||||
|
|
||||||
|
<button type="button" id="click-me">Click Me!</button>
|
||||||
|
<div id="output"></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
9
www/main.js
Normal file
9
www/main.js
Normal 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.";
|
||||||
|
}
|
||||||
|
});
|
Reference in New Issue
Block a user