80 lines
2.1 KiB
Rust
80 lines
2.1 KiB
Rust
|
use std::{
|
||
|
io::{prelude::*, BufReader},
|
||
|
net::{TcpListener, TcpStream},
|
||
|
process,
|
||
|
};
|
||
|
|
||
|
use ctrlc;
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
let (method, path) = (request_line_parts[0], request_line_parts[1]);
|
||
|
if method != "GET" {
|
||
|
http::responses::send_405(stream).unwrap_or_else(|_| error("Failed to send 405 response"));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
let path = if path.ends_with("/") {
|
||
|
&path[..path.len() - 1]
|
||
|
} else {
|
||
|
path
|
||
|
};
|
||
|
|
||
|
match path {
|
||
|
"/" => 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);
|
||
|
}
|