134 lines
4.1 KiB
Rust
Executable File
134 lines
4.1 KiB
Rust
Executable File
use std::{fs, time::Duration};
|
|
|
|
use std::net::TcpStream;
|
|
|
|
use serde_yml::{Number, Value};
|
|
use wildmatch::WildMatch;
|
|
|
|
use super::tls::TlsCertificate;
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct SiteConfig {
|
|
pub domain: WildMatch,
|
|
pub host: String,
|
|
pub ssl: Option<TlsCertificate>,
|
|
pub enable_keep_alive: bool,
|
|
pub support_keep_alive: bool,
|
|
pub ip_forwarding: IpForwarding,
|
|
pub replace_host: Option<String>
|
|
}
|
|
|
|
impl SiteConfig {
|
|
pub fn connect(&self) -> Option<TcpStream> {
|
|
TcpStream::connect(self.host.clone()).ok()
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub enum IpForwarding {
|
|
Simple,
|
|
Header(String),
|
|
Modern,
|
|
None
|
|
}
|
|
|
|
impl IpForwarding {
|
|
pub fn from_name(name: &str) -> Option<IpForwarding> {
|
|
match name {
|
|
"none" => Some(IpForwarding::None),
|
|
"simple" => Some(IpForwarding::Simple),
|
|
"modern" => Some(IpForwarding::Modern),
|
|
"header" => Some(IpForwarding::Header(String::from("X-Real-IP"))),
|
|
name => if name.starts_with("header:") {
|
|
Some(IpForwarding::Header(name[7..].to_string()))
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct Config {
|
|
pub sites: Vec<SiteConfig>,
|
|
pub http_host: Option<String>,
|
|
pub https_host: Option<String>,
|
|
pub connection_timeout: Duration,
|
|
pub incoming_ip_forwarding: IpForwarding,
|
|
pub threadpool_size: usize
|
|
}
|
|
|
|
impl Config {
|
|
pub fn parse(filename: &str) -> Option<Config> {
|
|
let file_content = fs::read_to_string(filename).ok()?;
|
|
let doc = serde_yml::from_str::<Value>(file_content.as_str()).ok()?;
|
|
|
|
let http_host = doc.get("http_host").and_then(|o| Some(o.as_str()?.to_string()));
|
|
let https_host = doc.get("https_host").and_then(|o| Some(o.as_str()?.to_string()));
|
|
|
|
let threadpool_size = doc.get("threadpool_size").and_then(|o| Some(o.as_u64()? as usize + 2)).unwrap_or(12);
|
|
|
|
let connection_timeout = Duration::from_secs(doc.get("connection_timeout")
|
|
.unwrap_or(&Value::Number(Number::from(10))).as_u64()?);
|
|
let incoming_ip_forwarding = doc.get("incoming_ip_forwarding")
|
|
.map(|o| o.as_str()).flatten()
|
|
.map(|o| IpForwarding::from_name(o)).flatten()
|
|
.unwrap_or(IpForwarding::None);
|
|
|
|
let mut sites: Vec<SiteConfig> = Vec::new();
|
|
|
|
let sites_yaml = doc["sites"].as_sequence()?;
|
|
|
|
for s in sites_yaml {
|
|
let mut cert: Option<TlsCertificate> = None;
|
|
let s = s.as_mapping()?;
|
|
|
|
if s.contains_key("ssl_cert") {
|
|
cert = Some(
|
|
TlsCertificate::new(
|
|
s.get("ssl_cert")?.as_str()?,
|
|
s.get("ssl_key")?.as_str()?,
|
|
)?,
|
|
);
|
|
}
|
|
|
|
let site = SiteConfig {
|
|
domain: WildMatch::new(&s.get("domain")?.as_str()?.to_string()),
|
|
host: s.get("host")?.as_str()?.to_string(),
|
|
ssl: cert,
|
|
enable_keep_alive: s.get("enable_keep_alive")
|
|
.map(|o| o.as_bool().unwrap())
|
|
.unwrap_or(true),
|
|
support_keep_alive: s.get("support_keep_alive")
|
|
.map(|o| o.as_bool().unwrap())
|
|
.unwrap_or(true),
|
|
ip_forwarding: s.get("ip_forwarding")
|
|
.map(|o| o.as_str()).flatten()
|
|
.map(|o| IpForwarding::from_name(o)).flatten()
|
|
.unwrap_or(IpForwarding::Header("X-Real-IP".to_string())),
|
|
replace_host: s.get("replace_host")
|
|
.map(|o| o.as_str()).flatten().map(|o| o.to_string()),
|
|
};
|
|
|
|
sites.push(site);
|
|
}
|
|
|
|
Some(Config {
|
|
sites,
|
|
http_host,
|
|
https_host,
|
|
connection_timeout,
|
|
incoming_ip_forwarding,
|
|
threadpool_size
|
|
}.clone())
|
|
}
|
|
|
|
pub fn get_site(&self, domain: &str) -> Option<&SiteConfig> {
|
|
for i in &self.sites {
|
|
if i.domain.matches(domain) {
|
|
return Some(i);
|
|
}
|
|
}
|
|
return None;
|
|
}
|
|
} |