use actix_web::middleware::Logger; use actix_web::{App, HttpResponse, HttpServer, web}; use clap::Parser; use hidden_server::restricted_port::is_restricted_port; use log::LevelFilter; use rand::Rng; async fn home() -> HttpResponse { log::info!("Successfully found the port!"); HttpResponse::Ok() .content_type("text/html") .body(include_str!("../assets/home.html")) } /// Server with hidden exposed port #[derive(Parser, Debug)] #[command(version, about, long_about = None)] struct Args { /// Minimal port this server will listen to #[arg(short('m'), long, default_value_t = 80)] min_port: u16, /// Maximal port this server will listen to #[arg(short('M'), long, default_value_t = 1000)] max_port: u16, /// Host this server will listen to #[arg(short, long, default_value = "0.0.0.0")] listen_host: String, } #[actix_web::main] async fn main() -> std::io::Result<()> { env_logger::Builder::new() .filter_module("actix_server::server", LevelFilter::Warn) .filter(None, LevelFilter::Info) .init(); let args: Args = Args::parse(); assert!( args.max_port > args.min_port, "Max port shall be greater than min port!" ); log::info!("Choosing a random port to start..."); let mut rng = rand::rng(); let mut port: u16; loop { port = args.min_port + rng.random::() % (args.max_port - args.min_port); if !is_restricted_port(port) { break; } log::info!("I chose a restricted port, I have to choose another one..."); } log::info!("Can now start server..."); HttpServer::new(|| { App::new() .wrap(Logger::default()) .route("/", web::get().to(home)) }) .bind((args.listen_host, port))? .run() .await } #[cfg(test)] mod test { use crate::Args; #[test] fn verify_cli() { use clap::CommandFactory; Args::command().debug_assert() } }