use std::{ io::{prelude::*, BufReader}, net::{TcpListener, TcpStream}, process, }; use ctrlc; use http::requests::URL; 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, url_str) = (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 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; } }; handle_request(url, stream); } fn handle_request(url: URL, stream: TcpStream) { match url.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); }