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); }