✨ Config loader
This commit is contained in:
		
							
								
								
									
										55
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										55
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @@ -216,7 +216,7 @@ dependencies = [ | |||||||
|  "rust-ini", |  "rust-ini", | ||||||
|  "serde", |  "serde", | ||||||
|  "serde_json", |  "serde_json", | ||||||
|  "toml", |  "toml 0.5.11", | ||||||
|  "yaml-rust", |  "yaml-rust", | ||||||
| ] | ] | ||||||
|  |  | ||||||
| @@ -1128,12 +1128,11 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" | |||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "proc-macro-crate" | name = "proc-macro-crate" | ||||||
| version = "2.0.1" | version = "2.0.0" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a" | checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "toml_datetime", |  "toml_edit 0.20.2", | ||||||
|  "toml_edit", |  | ||||||
| ] | ] | ||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| @@ -1246,11 +1245,14 @@ name = "roadsign" | |||||||
| version = "0.1.0" | version = "0.1.0" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "config", |  "config", | ||||||
|  |  "lazy_static", | ||||||
|  "poem", |  "poem", | ||||||
|  "poem-openapi", |  "poem-openapi", | ||||||
|  "serde", |  "serde", | ||||||
|  "serde_json", |  "serde_json", | ||||||
|  "tokio", |  "tokio", | ||||||
|  |  "toml 0.8.8", | ||||||
|  |  "tracing", | ||||||
|  "tracing-subscriber", |  "tracing-subscriber", | ||||||
| ] | ] | ||||||
|  |  | ||||||
| @@ -1352,6 +1354,15 @@ dependencies = [ | |||||||
|  "serde", |  "serde", | ||||||
| ] | ] | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "serde_spanned" | ||||||
|  | version = "0.6.5" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" | ||||||
|  | dependencies = [ | ||||||
|  |  "serde", | ||||||
|  | ] | ||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "serde_urlencoded" | name = "serde_urlencoded" | ||||||
| version = "0.7.1" | version = "0.7.1" | ||||||
| @@ -1629,10 +1640,25 @@ dependencies = [ | |||||||
| ] | ] | ||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "toml_datetime" | name = "toml" | ||||||
| version = "0.6.3" | version = "0.8.8" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | 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]] | [[package]] | ||||||
| name = "toml_edit" | name = "toml_edit" | ||||||
| @@ -1645,6 +1671,19 @@ dependencies = [ | |||||||
|  "winnow", |  "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]] | [[package]] | ||||||
| name = "tracing" | name = "tracing" | ||||||
| version = "0.1.40" | version = "0.1.40" | ||||||
|   | |||||||
| @@ -7,9 +7,12 @@ edition = "2021" | |||||||
|  |  | ||||||
| [dependencies] | [dependencies] | ||||||
| config = { version = "0.13.4", features = ["toml"] } | config = { version = "0.13.4", features = ["toml"] } | ||||||
|  | lazy_static = "1.4.0" | ||||||
| poem = { version = "2.0.0", features = ["tokio-metrics"] } | poem = { version = "2.0.0", features = ["tokio-metrics"] } | ||||||
| poem-openapi = "4.0.0" | poem-openapi = "4.0.0" | ||||||
| serde = "1.0.195" | serde = "1.0.195" | ||||||
| serde_json = "1.0.111" | serde_json = "1.0.111" | ||||||
| tokio = { version = "1.35.1", features = ["rt-multi-thread", "macros", "time"] } | tokio = { version = "1.35.1", features = ["rt-multi-thread", "macros", "time"] } | ||||||
|  | toml = "0.8.8" | ||||||
|  | tracing = "0.1.40" | ||||||
| tracing-subscriber = "0.3.18" | tracing-subscriber = "0.3.18" | ||||||
|   | |||||||
| @@ -1,3 +1,5 @@ | |||||||
|  | regions = "./regions" | ||||||
|  |  | ||||||
| [listen] | [listen] | ||||||
| proxies = "0.0.0.0:80" | proxies = "0.0.0.0:80" | ||||||
| proxies_tls = "0.0.0.0:443" | proxies_tls = "0.0.0.0:443" | ||||||
|   | |||||||
							
								
								
									
										9
									
								
								regions/index.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								regions/index.toml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | id = "index" | ||||||
|  |  | ||||||
|  | [[locations]] | ||||||
|  | id = "root" | ||||||
|  | hosts = ["localhost"] | ||||||
|  | paths = ["/"] | ||||||
|  | [[locations.destinations]] | ||||||
|  | id = "example" | ||||||
|  | uri = "https://example.com" | ||||||
| @@ -1 +1,12 @@ | |||||||
|  | use std::sync::RwLock; | ||||||
|  |  | ||||||
|  | use config::Config; | ||||||
|  | use lazy_static::lazy_static; | ||||||
|  |  | ||||||
|  | use crate::config::loader::load_settings; | ||||||
|  |  | ||||||
| pub mod loader; | pub mod loader; | ||||||
|  |  | ||||||
|  | lazy_static! { | ||||||
|  |     pub static ref C: RwLock<Config> = RwLock::new(load_settings()); | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										38
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								src/main.rs
									
									
									
									
									
								
							| @@ -4,21 +4,35 @@ mod sideload; | |||||||
|  |  | ||||||
| use poem::{listener::TcpListener, Route, Server}; | use poem::{listener::TcpListener, Route, Server}; | ||||||
| use poem_openapi::OpenApiService; | use poem_openapi::OpenApiService; | ||||||
|  | use tracing::{error, info, Level}; | ||||||
|  |  | ||||||
| #[tokio::main] | #[tokio::main] | ||||||
| async fn main() -> Result<(), std::io::Error> { | async fn main() -> Result<(), std::io::Error> { | ||||||
|     // Load settings |     // Setting up logging | ||||||
|     let settings = config::loader::load_settings(); |  | ||||||
|  |  | ||||||
|     println!( |  | ||||||
|         "Will listen at {:?}", |  | ||||||
|         settings.get_array("listen.proxies").unwrap() |  | ||||||
|     ); |  | ||||||
|  |  | ||||||
|     if std::env::var_os("RUST_LOG").is_none() { |     if std::env::var_os("RUST_LOG").is_none() { | ||||||
|         std::env::set_var("RUST_LOG", "poem=debug"); |         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 |     // Proxies | ||||||
|  |  | ||||||
| @@ -27,7 +41,9 @@ async fn main() -> Result<(), std::io::Error> { | |||||||
|         .server("http://localhost:3000/cgi"); |         .server("http://localhost:3000/cgi"); | ||||||
|  |  | ||||||
|     let sideload_server = Server::new(TcpListener::bind( |     let sideload_server = Server::new(TcpListener::bind( | ||||||
|         settings |         config::C | ||||||
|  |             .read() | ||||||
|  |             .unwrap() | ||||||
|             .get_string("listen.sideload") |             .get_string("listen.sideload") | ||||||
|             .unwrap_or("0.0.0.0:81".to_string()), |             .unwrap_or("0.0.0.0:81".to_string()), | ||||||
|     )) |     )) | ||||||
| @@ -37,3 +53,5 @@ async fn main() -> Result<(), std::io::Error> { | |||||||
|  |  | ||||||
|     Ok(()) |     Ok(()) | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 { | pub struct Region { | ||||||
|     id: String, |     id: String, | ||||||
|     locations: Vec<Location>, |     locations: Vec<Location>, | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Debug, Clone)] | #[derive(Debug, Clone, Serialize, Deserialize)] | ||||||
| pub struct Location { | pub struct Location { | ||||||
|  |     id: String, | ||||||
|     hosts: Vec<String>, |     hosts: Vec<String>, | ||||||
|     paths: Vec<String>, |     paths: Vec<String>, | ||||||
|     headers: Vec<HashMap<String, String>>, |     headers: Option<Vec<HashMap<String, String>>>, | ||||||
|     query_strings: Vec<HashMap<String, String>>, |     query_strings: Option<Vec<HashMap<String, String>>>, | ||||||
|     destination: Vec<Destination>, |     destinations: Vec<Destination>, | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Debug, Clone)] | #[derive(Debug, Clone, Serialize, Deserialize)] | ||||||
| pub struct Destination { | pub struct Destination { | ||||||
|     uri: Vec<String>, |     id: String, | ||||||
|     timeout: Duration, |     uri: String, | ||||||
|  |     timeout: Option<u32>, | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										53
									
								
								src/proxies/loader.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/proxies/loader.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -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<config::Region>, 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<config::Region, String> { | ||||||
|  |     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) | ||||||
|  | } | ||||||
| @@ -1 +1,17 @@ | |||||||
|  | use serde::{Deserialize, Serialize}; | ||||||
|  |  | ||||||
|  | use self::config::Region; | ||||||
|  |  | ||||||
| pub mod config; | pub mod config; | ||||||
|  | pub mod loader; | ||||||
|  |  | ||||||
|  | #[derive(Debug, Clone, Serialize, Deserialize)] | ||||||
|  | pub struct Instance { | ||||||
|  |     pub regions: Vec<Region>, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl Instance { | ||||||
|  |     pub fn new() -> Instance { | ||||||
|  |         Instance { regions: vec![] } | ||||||
|  |     } | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user