From 6164836cfc08e9b4120434755ede9d4f88426799 Mon Sep 17 00:00:00 2001 From: Andrew nuark G Date: Mon, 5 May 2025 20:03:16 +0700 Subject: [PATCH] feat: add domain-based index file selection and request logging --- Cargo.lock | 104 ++++++++++++++++++++++++++++++++++++++++++---------- Cargo.toml | 2 + src/main.rs | 64 ++++++++++++++++++++++++-------- 3 files changed, 135 insertions(+), 35 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c685420..cf25420 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "actix-codec" @@ -88,7 +88,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.66", + "syn 2.0.101", ] [[package]] @@ -204,7 +204,7 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.101", ] [[package]] @@ -434,7 +434,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.101", ] [[package]] @@ -534,7 +534,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.101", ] [[package]] @@ -546,6 +546,29 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "env_filter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "jiff", + "log", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -809,7 +832,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.101", ] [[package]] @@ -846,6 +869,30 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +[[package]] +name = "jiff" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07d8d955d798e7a4d6f9c58cd1f1916e790b42b092758a9ef6e16fef9f1b3fd" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", +] + +[[package]] +name = "jiff-static" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f244cfe006d98d26f859c7abd1318d85327e1882dc9cef80f62daeeb0adcf300" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "jobserver" version = "0.1.31" @@ -902,9 +949,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "memchr" @@ -1023,6 +1070,21 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +[[package]] +name = "portable-atomic" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -1037,18 +1099,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.85" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.36" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] @@ -1177,7 +1239,7 @@ checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.101", ] [[package]] @@ -1210,6 +1272,8 @@ dependencies = [ "actix-files", "actix-web", "clap", + "env_logger", + "log", ] [[package]] @@ -1282,9 +1346,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.66" +version = "2.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" dependencies = [ "proc-macro2", "quote", @@ -1299,7 +1363,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.101", ] [[package]] @@ -1632,7 +1696,7 @@ checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.101", "synstructure", ] @@ -1653,7 +1717,7 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.101", ] [[package]] @@ -1673,7 +1737,7 @@ checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.101", "synstructure", ] @@ -1696,7 +1760,7 @@ checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.101", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 8661a4c..ecd74e1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,3 +8,5 @@ authors = ["Andrew G. "] actix-web = "4.7.0" actix-files = "0.6.6" clap = { version = "4.5.7", features = ["derive"] } +env_logger = "0.11.8" +log = "0.4.27" diff --git a/src/main.rs b/src/main.rs index b473b8f..d68a5a0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,12 @@ use std::path::Path; +use std::collections::HashMap; use actix_files; use actix_web::{ - dev::{ServiceRequest, ServiceResponse}, - App, HttpServer, + dev::{ServiceRequest, ServiceResponse}, middleware::Logger, App, HttpServer }; use clap::{arg, command, Parser}; +use env_logger::Env; #[derive(Parser, Debug)] #[command(version, about, long_about = None)] @@ -24,10 +25,23 @@ struct ServantArgs { #[arg(long, default_value_t = String::from("index.html"))] index_file: String, + + #[arg(long = "rewrite-index", value_parser = parse_rewrite_index)] + rewrite_index: Vec<(String, String)>, +} + +fn parse_rewrite_index(s: &str) -> Result<(String, String), String> { + let parts: Vec<&str> = s.splitn(2, '=').collect(); + if parts.len() != 2 { + return Err("Expected format: domain=path".to_string()); + } + Ok((parts[0].to_string(), parts[1].to_string())) } #[actix_web::main] async fn main() -> std::io::Result<()> { + env_logger::init_from_env(Env::new().default_filter_or("info")); + let args = ServantArgs::parse(); let bind_addr = format!("{}:{}", args.host, args.port); @@ -39,23 +53,43 @@ async fn main() -> std::io::Result<()> { .to_string(); let mount_point = args.mount.clone(); + let serve_dir = args.serve_dir.clone(); + let default_index = args.index_file.clone(); + + let index_map: HashMap = args + .rewrite_index + .into_iter() + .collect(); HttpServer::new(move || { - let index_path = index_path.to_owned(); + let index_map = index_map.clone(); + let default_index = default_index.clone(); + let serve_dir = serve_dir.clone(); - App::new().service( - actix_files::Files::new(&mount_point, args.serve_dir.as_str()) - .index_file(args.index_file.as_str()) - .default_handler(move |req: ServiceRequest| { - let (http_req, _payload) = req.into_parts(); - let index_path = index_path.to_owned(); + App::new() + .wrap(Logger::default()) + .service( + actix_files::Files::new(&mount_point, &serve_dir) + .index_file(&default_index) + .default_handler(move |req: ServiceRequest| { + let (http_req, _payload) = req.into_parts(); + let host = http_req + .headers() + .get("Host") + .and_then(|h| h.to_str().ok()) + .unwrap_or_default(); - async { - let response = - actix_files::NamedFile::open(index_path)?.into_response(&http_req); - Ok(ServiceResponse::new(http_req, response)) - } - }), + // Determine the index file based on the host + let index_file = index_map + .get(host) + .cloned() + .unwrap_or_else(|| format!("{}/{}", serve_dir, default_index)); + + async move { + let response = actix_files::NamedFile::open(index_file)?.into_response(&http_req); + Ok(ServiceResponse::new(http_req, response)) + } + }), ) }) .bind(bind_addr)?