br-web-server 0.5.17

This is an WEB SERVER
Documentation
use json::{object, JsonValue};
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::{Path, PathBuf};

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Config {
    /// 调试
    pub debug: bool,
    /// 主机
    pub host: String,
    /// SSL/TLS
    pub https: bool,
    pub tls: TlsConfig,
    /// 日志记录
    pub log: bool,
    /// 运行根目录
    pub root_path: PathBuf,
    /// 公开目录
    pub public: String,
    /// 网页目录
    pub webpage: String,
    /// 运行时目录
    pub runtime: String,
    /// 语言
    pub charset: String,
    /// 密钥token
    pub token: String,
    /// 密钥文件路径
    pub pub_key_path: String,
    /// 最大请求体大小 (字节),默认 10MB
    #[serde(default = "default_max_body_size")]
    pub max_body_size: usize,
    /// 读取超时 (秒)
    #[serde(default = "default_read_timeout")]
    pub read_timeout: u64,
    /// 写入超时 (秒)
    #[serde(default = "default_write_timeout")]
    pub write_timeout: u64,
    /// 最大连接数,默认 1024
    #[serde(default = "default_max_connections")]
    pub max_connections: usize,
}

fn default_max_body_size() -> usize {
    10 * 1024 * 1024
}

fn default_read_timeout() -> u64 {
    30
}

fn default_write_timeout() -> u64 {
    30
}

fn default_max_connections() -> usize {
    1024
}
impl Config {
    #[must_use]
    pub fn default(path: PathBuf) -> Self {
        Self {
            debug: true,
            host: "0.0.0.0:3535".to_string(),
            https: false,
            tls: TlsConfig::new(),
            log: true,
            root_path: path,
            public: "public".to_string(),
            webpage: "spa".to_string(),
            runtime: "runtime".to_string(),
            charset: "utf-8".to_string(),
            token: String::new(),
            pub_key_path: String::new(),
            max_body_size: default_max_body_size(),
            read_timeout: default_read_timeout(),
            write_timeout: default_write_timeout(),
            max_connections: default_max_connections(),
        }
    }

    #[must_use]
    pub fn create(config_file: &Path, pkg_name: bool) -> Config {
        let dir = config_file.parent().unwrap_or(Path::new(".")).to_path_buf();
        #[derive(Clone, Debug, Deserialize, Serialize)]
        pub struct ConfigPkg {
            pub br_web_server: Config,
        }
        impl ConfigPkg {
            pub fn new(dir: PathBuf) -> ConfigPkg {
                Self {
                    br_web_server: Config::default(dir),
                }
            }
        }
        let mut data = Config::default(dir.clone());
        data.from();
        match fs::read_to_string(config_file) {
            Ok(e) => {
                if pkg_name {
                    match toml::from_str::<ConfigPkg>(&e) {
                        Ok(cfg) => cfg.br_web_server,
                        Err(_) => Config::default(dir),
                    }
                } else {
                    data
                }
            }
            Err(_) => {
                if pkg_name {
                    let data = ConfigPkg::new(dir);
                    let _ = fs::create_dir_all(config_file.parent().unwrap_or(Path::new(".")));
                    if let Ok(toml) = toml::to_string(&data) {
                        let _ = fs::write(config_file.to_str().unwrap_or(""), toml);
                    }
                    data.br_web_server
                } else {
                    let data = Config::default(dir);
                    let _ = fs::create_dir_all(config_file.parent().unwrap_or(Path::new(".")));
                    if let Ok(toml) = toml::to_string(&data) {
                        let _ = fs::write(config_file.to_str().unwrap_or(""), toml);
                    }
                    data
                }
            }
        }
    }
    fn from(&mut self) -> &mut Config {
        let root = self.root_path.clone();
        let runtime = root
            .join(self.runtime.clone())
            .to_str()
            .unwrap_or("")
            .to_string();
        let public = root
            .join(self.public.clone())
            .to_str()
            .unwrap_or("")
            .to_string();
        let webpage = root.join("webpage").to_str().unwrap_or("").to_string();
        let ssl = root.join("ssl").to_str().unwrap_or("").to_string();

        let _ = fs::create_dir_all(ssl.clone());
        let _ = fs::create_dir_all(runtime.clone());
        let _ = fs::create_dir_all(public.clone());
        let _ = fs::create_dir_all(webpage.clone());

        self
    }
    #[must_use]
    pub fn json(&self) -> JsonValue {
        object! {
            debug: self.debug,
            log: self.log,
            host: self.host.as_str(),
            https: self.https,
            root_path:self.root_path.to_str().unwrap_or(""),
            public: self.public.as_str(),
            webpage: self.webpage.as_str(),
            runtime: self.runtime.as_str(),
            charset: self.charset.as_str(),
            token: self.token.as_str(),
            pub_key_path: self.pub_key_path.as_str(),
            max_body_size: self.max_body_size,
            read_timeout: self.read_timeout,
            write_timeout: self.write_timeout,
            max_connections: self.max_connections,
        }
    }
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct TlsConfig {
    pub certs: PathBuf,
    pub key: PathBuf,
}
impl TlsConfig {
    fn new() -> Self {
        Self {
            certs: PathBuf::default(),
            key: PathBuf::default(),
        }
    }
    pub fn json(&self) -> JsonValue {
        object! {
            certs:self.certs.to_str().unwrap_or(""),
            key: self.key.to_str().unwrap_or(""),
        }
    }
    #[must_use]
    pub fn from(value: &JsonValue, root: &Path) -> Self {
        Self {
            certs: root.join(value["certs"].as_str().unwrap_or("")),
            key: root.join(value["key"].as_str().unwrap_or("")),
        }
    }
}