2024-10-29 20:58:10 +00:00
|
|
|
use std::{
|
|
|
|
io::{prelude::*, BufReader},
|
|
|
|
net::{TcpListener, TcpStream},
|
|
|
|
process,
|
|
|
|
};
|
|
|
|
|
|
|
|
use ctrlc;
|
2024-10-30 02:49:27 +00:00
|
|
|
use http::requests::URL;
|
2024-10-29 20:58:10 +00:00
|
|
|
|
|
|
|
mod http;
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
let listener =
|
|
|
|
TcpListener::bind("127.0.0.1:7878").unwrap_or_else(|_| fatal("Failed to bind to address"));
|
|
|
|
|
|
|
|
ctrlc::set_handler(move || {
|
|
|
|
println!("Shutting down...");
|
|
|
|
process::exit(0);
|
|
|
|
})
|
|
|
|
.unwrap_or_else(|_| fatal("Failed to set termination signal handler"));
|
|
|
|
|
|
|
|
for stream in listener.incoming() {
|
|
|
|
match stream {
|
|
|
|
Ok(stream) => {
|
|
|
|
handle_connection(stream);
|
|
|
|
}
|
|
|
|
Err(e) => {
|
|
|
|
eprintln!("Failed to establish connection: {}", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn handle_connection(mut stream: TcpStream) {
|
|
|
|
let reader = BufReader::new(&mut stream);
|
|
|
|
let mut lines = reader.lines();
|
|
|
|
|
|
|
|
let request_line = match lines.next() {
|
|
|
|
Some(Ok(line)) => line,
|
|
|
|
_ => {
|
|
|
|
http::responses::send_400(stream)
|
|
|
|
.unwrap_or_else(|_| error("Failed to send 400 response"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let request_line_parts: Vec<&str> = request_line.split_whitespace().collect();
|
|
|
|
if request_line_parts.len() != 3 {
|
|
|
|
http::responses::send_400(stream).unwrap_or_else(|_| error("Failed to send 400 response"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-10-30 02:49:27 +00:00
|
|
|
let (method, url_str) = (request_line_parts[0], request_line_parts[1]);
|
2024-10-29 20:58:10 +00:00
|
|
|
if method != "GET" {
|
|
|
|
http::responses::send_405(stream).unwrap_or_else(|_| error("Failed to send 405 response"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-10-30 02:49:27 +00:00
|
|
|
let url = match http::requests::URL::new(url_str) {
|
|
|
|
Some(path) => path,
|
|
|
|
None => {
|
|
|
|
http::responses::send_400(stream)
|
|
|
|
.unwrap_or_else(|_| error("Failed to send 400 response"));
|
|
|
|
return;
|
|
|
|
}
|
2024-10-29 20:58:10 +00:00
|
|
|
};
|
|
|
|
|
2024-10-30 02:49:27 +00:00
|
|
|
handle_request(url, stream);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn handle_request(url: URL, stream: TcpStream) {
|
|
|
|
match url.path {
|
2024-10-29 20:58:10 +00:00
|
|
|
"/" => http::responses::ok(stream, "OK - luciders is working!")
|
|
|
|
.unwrap_or_else(|_| error("Failed to send 200 response")),
|
|
|
|
_ => http::responses::send_404(stream)
|
|
|
|
.unwrap_or_else(|_| error("Failed to send 404 response")),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn fatal(msg: &'static str) -> ! {
|
|
|
|
eprintln!("[FATAL] {}", msg);
|
|
|
|
process::exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn error(msg: &'static str) {
|
|
|
|
eprintln!("[ERROR] {}", msg);
|
|
|
|
}
|