df-web 0.1.28

This is an WEB SERVER
Documentation
use std::io::{ErrorKind, Read, Write};
use std::net::{TcpListener, TcpStream};
use std::sync::Arc;
use std::{fs, io, thread};
use std::time::Duration;
use json::{JsonValue, object};
use log::info;
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
use crate::body::Body;
use crate::cors::Cors;
use crate::header::Header;

pub mod request;
mod cors;
pub mod header;
pub mod body;

#[derive(Clone, Debug)]
pub struct WebConfig {
    pub url: String,
    /// 域名
    pub domain: String,
    /// 对外访问目录
    pub public: String,
    /// 临时文件目录
    pub temp_dir: String,
    cors: Cors,
    ssl: bool,
    /// 私钥文件
    ssl_privkey: String,
    /// 公钥文件
    ssl_certs: String,
}

impl WebConfig {
    /// 默认
    pub fn default() -> Self {
        Self {
            url: "127.0.0.1:3535".to_string(),
            domain: "127.0.0.1:3535".to_string(),
            public: "./public".to_string(),
            temp_dir: "./temp".to_string(),
            cors: Cors {
                allow_origin: "*".to_string(),
                allow_methods: "GET,POST".to_string(),
                allow_headers: "api,token,mode,content-type".to_string(),
                allow_credentials: false,
                max_age: 10000000,
            },
            ssl: false,
            ssl_privkey: "".to_string(),
            ssl_certs: "".to_string(),
        }
    }
    /// 加载数据
    pub fn load(data: JsonValue) -> Self {
        let ssl = data["ssl"].as_bool().unwrap_or(false);
        let domain = if ssl {
            format!("https://{}", data["domain"].as_str().unwrap_or(""))
        } else {
            format!("http://{}", data["domain"].as_str().unwrap_or(""))
        };
        Self {
            url: data["url"].to_string(),
            domain,
            public: data["public"].to_string(),
            temp_dir: data["temp_dir"].to_string(),
            cors: Cors::load(data["cors"].clone()),
            ssl,
            ssl_privkey: data["ssl_privkey"].to_string(),
            ssl_certs: data["ssl_certs"].to_string(),
        }
    }
    pub fn to_json(self) -> JsonValue {
        let mut data = object! {};
        data["url"] = self.url.into();
        data["domain"] = self.domain.into();
        data["public"] = self.public.into();
        data["temp_dir"] = self.temp_dir.into();
        data["ssl"] = self.ssl.into();
        data["ssl_privkey"] = self.ssl_privkey.into();
        data["ssl_certs"] = self.ssl_certs.into();
        data["cors"] = self.cors.to_json();
        data
    }
}

pub struct WebService {}

impl WebService {
    pub fn bind(conf_path: &str, handle: fn(request: JsonValue) -> (i32, &'static str, JsonValue)) -> Result<(), io::Error> {
        let conf = match fs::read_to_string(conf_path) {
            Ok(content) => {
                if content == "" {
                    return Err(io::Error::new(ErrorKind::BrokenPipe, "请配置配置文件参数"));
                } else {
                    match json::parse(content.as_str()) {
                        Ok(e) => e,
                        Err(e) => {
                            return Err(io::Error::new(ErrorKind::BrokenPipe, e.to_string()));
                        }
                    }
                }
            }
            Err(e) => {
                if e.to_string().contains("No such file or directory") {
                    return Err(io::Error::new(ErrorKind::BrokenPipe, "请检查配置文件"));
                }
                return Err(io::Error::new(ErrorKind::BrokenPipe, e.to_string()));
            }
        };
        let config = WebConfig::load(conf);

        info!("web服务器启动 访问地址: {}",config.url);
        info!("公共目录: {}", config.public);
        info!("临时目录: {}", config.temp_dir);
        info!("ssl开启: {}", config.ssl);
        info!("根域名: {}", config.domain);

        let acceptor = {
            if config.ssl {
                info!("privkey: {}", config.ssl_privkey.clone());
                info!("certs: {}", config.ssl_certs.clone());
                let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
                acceptor.set_private_key_file(config.ssl_privkey.clone(), SslFiletype::PEM).unwrap();
                acceptor.set_certificate_chain_file(config.ssl_certs.clone()).unwrap();
                acceptor.check_private_key().unwrap();
                Arc::new(acceptor.build())
            } else {
                Arc::new(SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap().build())
            }
        };
        let config = config.clone();
        loop {
            let config = config.clone();
            match TcpListener::bind(config.url.as_str().clone()) {
                Ok(listener) => {
                    info!("服务启动成功");
                    for stream in listener.incoming() {
                        let header = Header { config: config.clone() };
                        let stream = stream.unwrap();
                        let acceptor = acceptor.clone();
                        thread::spawn(move || {
                            WebService::stream(stream.try_clone().unwrap(), acceptor.clone(), header.clone(), handle.clone());
                        });
                    }
                }
                Err(e) => {
                    info!("启动错误:{} 5秒后重启", e.to_string());
                    thread::sleep(Duration::from_secs(5));
                }
            }
        }
    }
    pub fn stream(stream: TcpStream, acceptor: Arc<SslAcceptor>, header: Header, handle: fn(request: JsonValue) -> (i32, &'static str, JsonValue)) {
        if header.config.ssl {
            WebService::https(stream.try_clone().unwrap(), acceptor, header, handle);
        } else {
            WebService::http(stream.try_clone().unwrap(), header, handle);
        }
    }
    pub fn http(mut stream: TcpStream, mut headers: Header, fun: fn(request: JsonValue) -> (i32, &'static str, JsonValue)) {
        let client_ip = stream.local_addr().unwrap().clone();
        let client_ip = client_ip.ip().to_string();


        let mut buf = vec![];
        let mut buffer = [0; 1024];
        let mut count = 1024;
        while count == 1024 {
            count = stream.read(&mut buffer).unwrap();
            buf = [buf, buffer[0..count].to_vec()].concat();
        }
        let data: String = buf.iter().map(|&c| c as char).collect();
        let mut header = headers.def(data.clone());
        header["client-ip"] = JsonValue::from(client_ip.clone());
        let data_length = header["data-length"].as_usize().unwrap();
        let body_length = header["content-length"].as_usize().unwrap();
        let header_length = header["header-length"].as_usize().unwrap();
        let mut mun = data_length - header_length;
        // 检查是否完整
        while mun < body_length {
            let mut buffer = [0; 1024];
            let count = stream.read(&mut buffer).unwrap();
            mun += count;
            buf = [buf, buffer[0..count].to_vec()].concat();
        };
        let body = Body::def(header.clone(), buf[header_length..].to_owned().clone());
        let (_, body) = request::Http::default(headers.config.cors.clone()).handle(header.clone(), body.clone(), fun);
        stream.write_all(body.as_bytes()).unwrap();
        stream.flush().unwrap();
    }
    pub fn https(stream: TcpStream, acceptor: Arc<SslAcceptor>, mut headers: Header, fun: fn(request: JsonValue) -> (i32, &'static str, JsonValue)) {
        let client_ip = stream.local_addr().unwrap().clone();
        let client_ip = client_ip.ip().to_string();

        match acceptor.accept(stream) {
            Ok(mut stream) => {
                let mut buf = vec![];
                let mut buffer = [0; 1024 * 10];
                let mut count = 1024;
                while count == 1024 {
                    count = stream.read(&mut buffer).unwrap();
                    buf = [buf, buffer[0..count].to_vec()].concat();
                }
                let data: String = buf.iter().map(|&c| c as char).collect();
                let mut header = headers.def(data.clone());
                header["client-ip"] = JsonValue::from(client_ip.clone());
                let data_length = header["data-length"].as_usize().unwrap();
                let body_length = header["content-length"].as_usize().unwrap();
                let header_length = header["header-length"].as_usize().unwrap();
                let mut mun = data_length - header_length;
                // 检查是否完整
                while mun < body_length {
                    let mut buffer = [0; 1024];
                    let count = stream.read(&mut buffer).unwrap();
                    mun += count;
                    buf = [buf, buffer[0..count].to_vec()].concat();
                };
                let body = Body::def(header.clone(), buf[header_length..].to_owned().clone());
                let (state, body) = request::Http::default(headers.config.cors.clone()).handle(header.clone(), body.clone(), fun);
                if state {
                    stream.ssl_write(body.as_bytes()).unwrap();
                    stream.flush().unwrap();
                }
            }
            Err(e) => {
                info!("{}",e.to_string());
            }
        }
    }
}