use std::{ net::{IpAddr, SocketAddr}, num::NonZeroUsize, path::PathBuf, thread::available_parallelism, }; use actix_web::{App, HttpServer}; use clap::{crate_name, crate_version, Parser}; #[derive(Parser, Debug)] #[clap(name = crate_name!(), version = crate_version!())] struct Args { /// Directory to expose #[clap(default_value = ".", value_parser = parse_valid_dir)] dir: PathBuf, /// IP address to use #[clap(default_value = "0.0.0.0")] ip: IpAddr, /// Port number to connect #[clap(default_value = "8080")] port: u16, } fn parse_valid_dir(dir: &str) -> Result { let path = std::path::Path::new(dir); if path.is_dir() { Ok(path.to_path_buf()) } else { Err(format!("{} is not a valid directory", path.display())) } } #[actix_web::main] async fn main() -> std::io::Result<()> { let args = Args::parse(); let dir = args.dir; let sock = SocketAddr::new(args.ip, args.port); println!( "Starting HTTP server on {sock} exposing dir {}", dir.display() ); HttpServer::new(move || { App::new().service( actix_files::Files::new("/", dir.clone()) .show_files_listing() .prefer_utf8(true), ) }) .workers(available_parallelism().map_or(1, NonZeroUsize::get)) .bind(sock)? .run() .await }