2024-11-01 10:59:38 +00:00
|
|
|
use std::{env, ffi::OsString, fs, net::TcpListener, process};
|
2024-10-29 20:58:10 +00:00
|
|
|
|
|
|
|
use ctrlc;
|
2024-11-01 10:59:38 +00:00
|
|
|
use http::responses::{Response, Body};
|
2024-10-29 20:58:10 +00:00
|
|
|
|
2024-11-01 08:35:25 +00:00
|
|
|
mod handlers;
|
2024-10-29 20:58:10 +00:00
|
|
|
mod http;
|
|
|
|
|
|
|
|
fn main() {
|
2024-11-01 10:59:38 +00:00
|
|
|
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());
|
|
|
|
|
2024-10-29 20:58:10 +00:00
|
|
|
let listener =
|
2024-11-01 08:48:55 +00:00
|
|
|
TcpListener::bind("[::]:7878").unwrap_or_else(|_| fatal("Failed to bind to address"));
|
2024-10-29 20:58:10 +00:00
|
|
|
|
|
|
|
ctrlc::set_handler(move || {
|
|
|
|
println!("Shutting down...");
|
|
|
|
process::exit(0);
|
|
|
|
})
|
|
|
|
.unwrap_or_else(|_| fatal("Failed to set termination signal handler"));
|
|
|
|
|
2024-11-01 08:35:25 +00:00
|
|
|
let mut handlers = handlers::Handlers::new();
|
2024-10-29 20:58:10 +00:00
|
|
|
|
2024-11-01 08:35:25 +00:00
|
|
|
handlers.add_handler("/", |req| {
|
2024-11-01 10:59:38 +00:00
|
|
|
if req.method != "GET" {
|
|
|
|
return Response::new(req, 405, Body::Static("Method Not Allowed"));
|
2024-10-29 20:58:10 +00:00
|
|
|
}
|
2024-11-01 10:59:38 +00:00
|
|
|
|
|
|
|
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"));
|
2024-11-01 08:35:25 +00:00
|
|
|
});
|
2024-10-30 02:49:27 +00:00
|
|
|
|
2024-11-01 08:35:25 +00:00
|
|
|
handlers.bind(listener);
|
2024-10-29 20:58:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn fatal(msg: &'static str) -> ! {
|
|
|
|
eprintln!("[FATAL] {}", msg);
|
|
|
|
process::exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn error(msg: &'static str) {
|
|
|
|
eprintln!("[ERROR] {}", msg);
|
|
|
|
}
|