From 5de1d139077fc8eeca06f0645b8c81f6d1e59d3f Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sat, 13 Jan 2024 14:46:26 +0800 Subject: [PATCH] :sparkles: Config loader --- Cargo.lock | 55 ++++++++++++++++++++++++++++++++++++------- Cargo.toml | 3 +++ Settings.toml | 2 ++ regions/index.toml | 9 +++++++ src/config/mod.rs | 11 +++++++++ src/main.rs | 38 ++++++++++++++++++++++-------- src/proxies/config.rs | 22 ++++++++++------- src/proxies/loader.rs | 53 +++++++++++++++++++++++++++++++++++++++++ src/proxies/mod.rs | 16 +++++++++++++ 9 files changed, 182 insertions(+), 27 deletions(-) create mode 100644 regions/index.toml create mode 100644 src/proxies/loader.rs diff --git a/Cargo.lock b/Cargo.lock index da66b14..5580b7b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -216,7 +216,7 @@ dependencies = [ "rust-ini", "serde", "serde_json", - "toml", + "toml 0.5.11", "yaml-rust", ] @@ -1128,12 +1128,11 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro-crate" -version = "2.0.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a" +checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" dependencies = [ - "toml_datetime", - "toml_edit", + "toml_edit 0.20.2", ] [[package]] @@ -1246,11 +1245,14 @@ name = "roadsign" version = "0.1.0" dependencies = [ "config", + "lazy_static", "poem", "poem-openapi", "serde", "serde_json", "tokio", + "toml 0.8.8", + "tracing", "tracing-subscriber", ] @@ -1352,6 +1354,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -1629,10 +1640,25 @@ dependencies = [ ] [[package]] -name = "toml_datetime" -version = "0.6.3" +name = "toml" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.21.0", +] + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +dependencies = [ + "serde", +] [[package]] name = "toml_edit" @@ -1645,6 +1671,19 @@ dependencies = [ "winnow", ] +[[package]] +name = "toml_edit" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "tracing" version = "0.1.40" diff --git a/Cargo.toml b/Cargo.toml index 6581414..510e222 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,9 +7,12 @@ edition = "2021" [dependencies] config = { version = "0.13.4", features = ["toml"] } +lazy_static = "1.4.0" poem = { version = "2.0.0", features = ["tokio-metrics"] } poem-openapi = "4.0.0" serde = "1.0.195" serde_json = "1.0.111" tokio = { version = "1.35.1", features = ["rt-multi-thread", "macros", "time"] } +toml = "0.8.8" +tracing = "0.1.40" tracing-subscriber = "0.3.18" diff --git a/Settings.toml b/Settings.toml index fc76f4a..d1fc034 100644 --- a/Settings.toml +++ b/Settings.toml @@ -1,3 +1,5 @@ +regions = "./regions" + [listen] proxies = "0.0.0.0:80" proxies_tls = "0.0.0.0:443" diff --git a/regions/index.toml b/regions/index.toml new file mode 100644 index 0000000..b234b05 --- /dev/null +++ b/regions/index.toml @@ -0,0 +1,9 @@ +id = "index" + +[[locations]] +id = "root" +hosts = ["localhost"] +paths = ["/"] +[[locations.destinations]] +id = "example" +uri = "https://example.com" diff --git a/src/config/mod.rs b/src/config/mod.rs index 186dcf6..c7507d4 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -1 +1,12 @@ +use std::sync::RwLock; + +use config::Config; +use lazy_static::lazy_static; + +use crate::config::loader::load_settings; + pub mod loader; + +lazy_static! { + pub static ref C: RwLock = RwLock::new(load_settings()); +} diff --git a/src/main.rs b/src/main.rs index ff651b5..dfdea62 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,21 +4,35 @@ mod sideload; use poem::{listener::TcpListener, Route, Server}; use poem_openapi::OpenApiService; +use tracing::{error, info, Level}; #[tokio::main] async fn main() -> Result<(), std::io::Error> { - // Load settings - let settings = config::loader::load_settings(); - - println!( - "Will listen at {:?}", - settings.get_array("listen.proxies").unwrap() - ); - + // Setting up logging if std::env::var_os("RUST_LOG").is_none() { std::env::set_var("RUST_LOG", "poem=debug"); } - tracing_subscriber::fmt::init(); + tracing_subscriber::fmt() + .with_max_level(Level::DEBUG) + .init(); + + // Prepare all the stuff + let mut instance = proxies::Instance::new(); + + info!("Loading proxy regions..."); + match proxies::loader::scan_regions( + config::C + .read() + .unwrap() + .get_string("regions") + .unwrap_or("./regions".to_string()), + ) { + Err(_) => error!("Loading proxy regions... failed"), + Ok((regions, count)) => { + instance.regions = regions; + info!(count, "Loading proxy regions... done") + } + }; // Proxies @@ -27,7 +41,9 @@ async fn main() -> Result<(), std::io::Error> { .server("http://localhost:3000/cgi"); let sideload_server = Server::new(TcpListener::bind( - settings + config::C + .read() + .unwrap() .get_string("listen.sideload") .unwrap_or("0.0.0.0:81".to_string()), )) @@ -37,3 +53,5 @@ async fn main() -> Result<(), std::io::Error> { Ok(()) } + + diff --git a/src/proxies/config.rs b/src/proxies/config.rs index 435977c..a7ab6a1 100644 --- a/src/proxies/config.rs +++ b/src/proxies/config.rs @@ -1,22 +1,26 @@ -use std::{collections::HashMap, time::Duration}; +use std::collections::HashMap; -#[derive(Debug, Clone)] +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct Region { id: String, locations: Vec, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct Location { + id: String, hosts: Vec, paths: Vec, - headers: Vec>, - query_strings: Vec>, - destination: Vec, + headers: Option>>, + query_strings: Option>>, + destinations: Vec, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct Destination { - uri: Vec, - timeout: Duration, + id: String, + uri: String, + timeout: Option, } diff --git a/src/proxies/loader.rs b/src/proxies/loader.rs new file mode 100644 index 0000000..0928e00 --- /dev/null +++ b/src/proxies/loader.rs @@ -0,0 +1,53 @@ +use std::ffi::OsStr; +use std::fs::{self, DirEntry}; +use std::io; + +use tracing::warn; + +use crate::proxies::config; + +pub fn scan_regions(basepath: String) -> io::Result<(Vec, u32)> { + let mut count: u32 = 0; + let mut result = vec![]; + for entry in fs::read_dir(basepath)? { + if let Ok(val) = load_region(entry.unwrap()) { + result.push(val); + count += 1; + }; + } + + Ok((result, count)) +} + +pub fn load_region(file: DirEntry) -> Result { + if file.path().extension().and_then(OsStr::to_str).unwrap() != "toml" { + return Err("File entry wasn't toml file".to_string()); + } + + let fp = file.path(); + let content = match fs::read_to_string(fp.clone()) { + Ok(val) => val, + Err(err) => { + warn!( + err = format!("{:?}", err), + filepath = fp.clone().to_str(), + "An error occurred when loading region, skipped." + ); + return Err("Failed to load file".to_string()); + } + }; + + let data: config::Region = match toml::from_str(&content) { + Ok(val) => val, + Err(err) => { + warn!( + err = format!("{:?}", err), + filepath = fp.clone().to_str(), + "An error occurred when parsing region, skipped." + ); + return Err("Failed to parse file".to_string()); + } + }; + + Ok(data) +} diff --git a/src/proxies/mod.rs b/src/proxies/mod.rs index ef68c36..2f5af48 100644 --- a/src/proxies/mod.rs +++ b/src/proxies/mod.rs @@ -1 +1,17 @@ +use serde::{Deserialize, Serialize}; + +use self::config::Region; + pub mod config; +pub mod loader; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Instance { + pub regions: Vec, +} + +impl Instance { + pub fn new() -> Instance { + Instance { regions: vec![] } + } +}