use std::{env, ffi::OsString, fs, net::TcpListener, process}; use ctrlc; use http::responses::{Response, Body}; mod handlers; mod http; fn main() { println!("luciders starting..."); let icons_dir_arg = env::args_os() .nth(1) .unwrap_or(OsString::from("vendor/lucide/icons")); println!("Using icons from: {:?}", icons_dir_arg); let icon_filenames: Vec<_> = fs::read_dir(icons_dir_arg) .unwrap_or_else(|_| fatal("Failed to read icons directory! Does the path exist?")) .map(|entry| entry.unwrap_or_else(|_| fatal("Failed to read icon entry"))) .map(|entry| entry.file_name()) .filter(|entry| entry.to_str().unwrap_or("").ends_with(".svg")) .collect(); println!("Found {} icons", icon_filenames.len()); let listener = TcpListener::bind("[::]: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")); let mut handlers = handlers::Handlers::new(); handlers.add_handler("/", |req| { if req.method != "GET" { return Response::new(req, 405, Body::Static("Method Not Allowed")); } Response::new(req, 200, Body::Static("OK - luciders is running")) }); handlers.add_handler("/icons/[icon].png", move |req| { if req.method != "GET" { return Response::new(req, 405, Body::Static("Method Not Allowed")); } let icon_name = match req.url.get_path_segment(1) { Some(icon) => icon, None => return Response::new(req, 404, Body::Static("Icon Not Found")), }; if !icon_filenames.contains(&OsString::from(&icon_name[..icon_name.len() - 4])) { return Response::new(req, 404, Body::Static("Icon Not Found")); } return Response::new(req, 200, Body::Static("Icon Not Found")); }); handlers.bind(listener); } fn fatal(msg: &'static str) -> ! { eprintln!("[FATAL] {}", msg); process::exit(1); } fn error(msg: &'static str) { eprintln!("[ERROR] {}", msg); }