diff --git a/.gitignore b/.gitignore index 03e9dc5..080988b 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ /target/ *.iml .idea/ +.etc/ *.ipr *.iws /out/ diff --git a/src/utils/consul.rs b/src/utils/consul.rs index 7a25c83..afb94a7 100644 --- a/src/utils/consul.rs +++ b/src/utils/consul.rs @@ -1,5 +1,5 @@ use crate::utils::parceyaml::load_configuration; -use crate::utils::structs::{Configuration, ServiceMapping, UpstreamsDashMap}; +use crate::utils::structs::{Configuration, InnerMap, ServiceMapping, UpstreamsDashMap}; use crate::utils::tools::{clone_dashmap_into, compare_dashmaps}; use dashmap::DashMap; use futures::channel::mpsc::Sender; @@ -109,7 +109,7 @@ async fn consul_request(url: String, whitelist: Option>, tok Some(upstreams) } -async fn get_by_http(url: String, token: Option) -> Option, AtomicUsize)>> { +async fn get_by_http(url: String, token: Option) -> Option, AtomicUsize)>> { let client = reqwest::Client::new(); let mut headers = HeaderMap::new(); if let Some(token) = token { @@ -118,7 +118,7 @@ async fn get_by_http(url: String, token: Option) -> Option, AtomicUsize)> = DashMap::new(); + let upstreams: DashMap, AtomicUsize)> = DashMap::new(); match u.await { Ok(r) => { let jason = r.json::>().await; @@ -127,7 +127,13 @@ async fn get_by_http(url: String, token: Option) -> Option, fullist: Arc, idlist: Arc, params: (&str, u64)) { let mut period = interval(Duration::from_secs(params.1)); let mut first_run = 0; @@ -20,47 +21,41 @@ pub async fn hc2(upslist: Arc, fullist: Arc, for val in fclone.iter() { let host = val.key(); let inner = DashMap::new(); - let mut _scheme: (String, u16, bool, bool, bool) = ("".to_string(), 0, false, false, false); + let mut scheme = InnerMap::new(); for path_entry in val.value().iter() { - // let inner = DashMap::new(); let path = path_entry.key(); let mut innervec= Vec::new(); for k in path_entry.value().0 .iter().enumerate() { - let (ip, port, _ssl, _version, _redir) = k.1; let mut _link = String::new(); - let tls = detect_tls(ip, port).await; + let tls = detect_tls(k.1.address.as_str(), &k.1.port).await; let mut is_h2 = false; - - // if tls.1 == Some(Version::HTTP_11) { - // println!(" V1: ==> {:?}", tls.1) - // }else if tls.1 == Some(Version::HTTP_2) { - // is_h2 = true; - // println!(" V2: ==> {:?}", tls.1) - // } - if tls.1 == Some(Version::HTTP_2) { is_h2 = true; - // println!(" V2: ==> {} ==> {:?}", tls.0, tls.1) } - match tls.0 { - true => _link = format!("https://{}:{}{}", ip, port, path), - false => _link = format!("http://{}:{}{}", ip, port, path), + true => _link = format!("https://{}:{}{}", k.1.address, k.1.port, path), + false => _link = format!("http://{}:{}{}", k.1.address, k.1.port, path), } - // if _pref == "https://" { - // _scheme = (ip.to_string(), *port, true); - // }else { - // _scheme = (ip.to_string(), *port, false); - // } - _scheme = (ip.to_string(), *port, tls.0, is_h2, *_redir); - // let link = format!("{}{}:{}{}", _pref, ip, port, path); + scheme = InnerMap { + address: k.1.address.clone(), + port: k.1.port, + is_ssl: tls.0, + is_http2: is_h2, + to_https: k.1.to_https, + }; let resp = http_request(_link.as_str(), params.0, "").await; match resp.0 { true => { if resp.1 { - _scheme = (ip.to_string(), *port, tls.0, true, *_redir); + scheme = InnerMap { + address: k.1.address.clone(), + port: k.1.port, + is_ssl: tls.0, + is_http2: is_h2, + to_https: k.1.to_https, + }; } - innervec.push(_scheme.clone()); + innervec.push(scheme); } false => { warn!("Dead Upstream : {}", _link); diff --git a/src/utils/parceyaml.rs b/src/utils/parceyaml.rs index 4f4a9ec..cfb6f64 100644 --- a/src/utils/parceyaml.rs +++ b/src/utils/parceyaml.rs @@ -89,9 +89,15 @@ pub fn load_configuration(d: &str, kind: &str) -> Option { for server in path_config.servers { if let Some((ip, port_str)) = server.split_once(':') { if let Ok(port) = port_str.parse::() { - // let to_https = matches!(path_config.to_https, Some(true)); let to_https = path_config.to_https.unwrap_or(false); - server_list.push((ip.to_string(), port, true, false, to_https)); + let sl = InnerMap { + address: ip.to_string(), + port: port, + is_ssl: true, + is_http2: false, + to_https: to_https, + }; + server_list.push(sl); } } } diff --git a/src/utils/structs.rs b/src/utils/structs.rs index 4a05a25..7dfd286 100644 --- a/src/utils/structs.rs +++ b/src/utils/structs.rs @@ -3,12 +3,12 @@ use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::sync::atomic::AtomicUsize; -pub type InnerMap = (String, u16, bool, bool, bool); +// pub type InnerMap = BackendConfig; pub type UpstreamsDashMap = DashMap, AtomicUsize)>>; pub type UpstreamsIdMap = DashMap; pub type Headers = DashMap>>; -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Default, Clone, Serialize, Deserialize)] pub struct ServiceMapping { pub proxy: String, pub real: String, @@ -22,32 +22,38 @@ pub struct Extraparams { pub rate_limit: Option, } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Default, Debug, Serialize, Deserialize)] pub struct Consul { pub servers: Option>, pub services: Option>, pub token: Option, } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Default, Serialize, Deserialize)] pub struct Config { pub provider: String, pub sticky_sessions: bool, pub to_https: Option, + #[serde(default)] pub upstreams: Option>, + #[serde(default)] pub globals: Option>>, + #[serde(default)] pub headers: Option>, + #[serde(default)] pub authorization: Option>, + #[serde(default)] pub consul: Option, + #[serde(default)] pub rate_limit: Option, } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Default, Serialize, Deserialize)] pub struct HostConfig { pub paths: HashMap, pub rate_limit: Option, } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Default, Serialize, Deserialize)] pub struct PathConfig { pub servers: Vec, pub to_https: Option, @@ -63,7 +69,7 @@ pub struct Configuration { pub extraparams: Extraparams, } -#[derive(Debug, Deserialize)] +#[derive(Debug, Default, Serialize, Deserialize)] pub struct AppConfig { pub hc_interval: u16, pub hc_method: String, @@ -83,3 +89,62 @@ pub struct AppConfig { pub file_server_address: Option, pub file_server_folder: Option, } + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct InnerMap { + pub address: String, + pub port: u16, + pub is_ssl: bool, + pub is_http2: bool, + pub to_https: bool, +} + +impl InnerMap { + pub fn new() -> Self { + Self { + address: String::new(), + port: 0, + is_ssl: false, + is_http2: false, + to_https: false, + } + } +} + +/* +impl InnerMap { + pub fn new(address: String, port: u16) -> Self { + Self { + address, + port, + is_ssl: false, // Default values + is_http2: false, + to_https: false, + } + } + pub fn address(&self) -> &str { + &self.address + } + + pub fn port(&self) -> u16 { + self.port + } + + // Setters with validation + pub fn with_ssl(mut self, ssl: bool) -> Result { + self.is_ssl = ssl; + Ok(self) + } + + pub fn with_http2(mut self, http2: bool) -> Result { + self.is_http2 = http2; + Ok(self) + } + + pub fn with_to_https(mut self, to_https: bool) -> Result { + self.to_https = to_https; + Ok(self) + } +} + +*/ diff --git a/src/utils/tools.rs b/src/utils/tools.rs index 3d06fcb..f4c5f77 100644 --- a/src/utils/tools.rs +++ b/src/utils/tools.rs @@ -1,4 +1,4 @@ -use crate::utils::structs::{UpstreamsDashMap, UpstreamsIdMap}; +use crate::utils::structs::{InnerMap, UpstreamsDashMap, UpstreamsIdMap}; use crate::utils::tls; use crate::utils::tls::CertificateConfig; use dashmap::DashMap; @@ -22,10 +22,16 @@ pub fn print_upstreams(upstreams: &UpstreamsDashMap) { for path_entry in host_entry.value().iter() { let path = path_entry.key(); println!(" Path: {}", path); - - for (ip, port, ssl, vers, to_https) in path_entry.value().0.clone() { - println!(" ===> IP: {}, Port: {}, SSL: {}, H2: {}, To HTTPS: {}", ip, port, ssl, vers, to_https); + for f in path_entry.value().0.clone() { + println!( + " ===> IP: {}, Port: {}, SSL: {}, H2: {}, To HTTPS: {}", + f.address, f.port, f.is_ssl, f.is_http2, f.to_https + ); } + // { address: "127.0.0.4", port: 8000, is_ssl: false, is_http2: false, to_https: false } + // for (ip, port, ssl, vers, to_https) in path_entry.value().0.clone() { + // println!(" ===> IP: {}, Port: {}, SSL: {}, H2: {}, To HTTPS: {}", ip, port, ssl, vers, to_https); + // } } } } @@ -140,13 +146,20 @@ pub fn clone_idmap_into(original: &UpstreamsDashMap, cloned: &UpstreamsIdMap) { let new_vec = vec.clone(); for x in vec.iter() { let mut id = String::new(); - write!(&mut id, "{}:{}:{}", x.0, x.1, x.2).unwrap(); + write!(&mut id, "{}:{}:{}", x.address, x.port, x.is_ssl).unwrap(); let mut hasher = Sha256::new(); hasher.update(id.clone().into_bytes()); let hash = hasher.finalize(); let hex_hash = base16ct::lower::encode_string(&hash); let hh = hex_hash[0..50].to_string(); - cloned.insert(id, (hh.clone(), 0000, false, false, false)); + let to_add = InnerMap { + address: hh.clone(), + port: 0, + is_ssl: false, + is_http2: false, + to_https: false, + }; + cloned.insert(id, to_add); cloned.insert(hh, x.to_owned()); } new_inner_map.insert(path.clone(), new_vec); diff --git a/src/web/gethosts.rs b/src/web/gethosts.rs index 5670f4c..0f97ef6 100644 --- a/src/web/gethosts.rs +++ b/src/web/gethosts.rs @@ -45,7 +45,6 @@ impl GetHost for LB { } } } - // println!("BMT :===> {:?}", best_match); best_match } fn get_header(&self, peer: &str, path: &str) -> Option> { diff --git a/src/web/proxyhttp.rs b/src/web/proxyhttp.rs index afb1dc6..4a70824 100644 --- a/src/web/proxyhttp.rs +++ b/src/web/proxyhttp.rs @@ -104,22 +104,23 @@ impl ProxyHttp for LB { } } - let ddr = self.get_host(hostname, hostname, backend_id); + let optioninnermap = self.get_host(hostname, hostname, backend_id); - match ddr { - Some((address, port, ssl, is_h2, to_https)) => { - let mut peer = Box::new(HttpPeer::new((address.clone(), port.clone()), ssl, String::new())); + match optioninnermap { + // Some((address, port, ssl, is_h2, to_https)) => { + Some(innermap) => { + let mut peer = Box::new(HttpPeer::new((innermap.address.clone(), innermap.port.clone()), innermap.is_ssl, String::new())); // if session.is_http2() { - if is_h2 { + if innermap.is_http2 { peer.options.alpn = ALPN::H2; } - if ssl { + if innermap.is_ssl { peer.sni = hostname.clone(); peer.options.verify_cert = false; peer.options.verify_hostname = false; } - if self.extraparams.load().to_https.unwrap_or(false) || to_https { + if self.extraparams.load().to_https.unwrap_or(false) || innermap.to_https { if let Some(stream) = session.stream() { if stream.get_ssl().is_none() { if let Some(addr) = session.server_addr() { @@ -134,7 +135,7 @@ impl ProxyHttp for LB { } } - ctx.backend_id = format!("{}:{}:{}", address.clone(), port.clone(), ssl); + ctx.backend_id = format!("{}:{}:{}", innermap.address.clone(), innermap.port.clone(), innermap.is_ssl); Ok(peer) } None => { @@ -193,7 +194,7 @@ impl ProxyHttp for LB { if self.extraparams.load().sticky_sessions { let backend_id = ctx.backend_id.clone(); if let Some(bid) = self.ump_byid.get(&backend_id) { - let _ = _upstream_response.insert_header("set-cookie", format!("backend_id={}; Path=/; Max-Age=600; HttpOnly; SameSite=Lax", bid.0)); + let _ = _upstream_response.insert_header("set-cookie", format!("backend_id={}; Path=/; Max-Age=600; HttpOnly; SameSite=Lax", bid.address)); } } if ctx.to_https {