br-web-server 0.2.30

This is an WEB SERVER
Documentation
mod base64;
mod client;
pub mod config;
mod encoding;
pub mod request;
pub mod response;
pub mod websocket;
use crate::client::{Client, Scheme};
use crate::config::{Config};
use crate::request::Request;
use crate::response::Response;
use crate::websocket::{CloseCode, ErrorCode, Message, Websocket};
use log::{error, info, warn};
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
use std::io::{Error};
use std::net::{IpAddr, SocketAddr, TcpListener};
use std::sync::Arc;
use std::time::Duration;
use std::{io, thread};
/// 网络服务
#[derive(Clone, Debug)]
pub struct WebServer;

impl WebServer {
    #[cfg(feature = "service")]
    /// 后台服务器
    pub fn new_service(config: &Config, factory: fn(config: Config) -> Box<dyn Handler>) {
        loop {
            {
                match WebServer::service(&config.clone(), factory) {
                    Ok(()) => {}
                    Err(e) => error!("服务器错误: {}[{}]: {}", file!(), line!(), e),
                }
            }
            warn!("服务器 1秒后重启");
            thread::sleep(Duration::from_secs(1));
        }
    }
    #[cfg(feature = "service")]
    fn service(config: &Config, factory: fn(config: Config) -> Box<dyn Handler>) -> io::Result<()> {
        info!("==================== 网络服务 服务信息 ====================");
        info!("日志记录: {}",if config.is_save_log {"开启"} else {"关闭"});
        info!("调试模式: {}",if config.is_debug { "开启" } else { "关闭" });
        info!("地    址: {}", config.host);
        info!("端 口 号: {}", config.port);
        info!("服务地址: {}://{}{}",if config.https { "https" } else { "http" },config.host,if config.port > 0 {format!(":{}", config.port)} else {String::new()});
        info!("根 目 录: {}", config.root_path.to_str().unwrap());
        info!("访问目录: {}", config.public);
        info!("运行目录: {}", config.runtime);
        info!("SSL/TLS: {}",if config.https { "开启" } else { "关闭" });

        if config.https {
            info!("证书目录KEY: {:?}", config.tls.key);
            info!("证书目录PEM: {:?}", config.tls.certs);
        }

        let addrs = [SocketAddr::from((
            IpAddr::V4(config.host.parse().unwrap()),
            config.port,
        ))];
        let listener = TcpListener::bind(&addrs[..])?;
        info!("==================== 网络服务 启动成功 ====================");

        let acceptor = Self::ssl(&config.clone())?;
        for stream in listener.incoming() {
            {
                match stream {
                    Ok(stream) => {
                        let config_new = config.clone();
                        let acceptor_new = acceptor.clone();
                        thread::spawn(move || {
                            // 设置超时时间
                            if config_new.write_timeout > 0 {
                                stream.set_write_timeout(Some(Duration::from_secs(config_new.write_timeout))).unwrap_or_default();
                            }
                            if config_new.read_timeout > 0 {
                                stream.set_read_timeout(Some(Duration::from_secs(config_new.read_timeout))).unwrap_or_default();
                            }

                            // 获取请求客户端IP
                            let client_ip = stream.peer_addr().unwrap().ip().to_string();
                            // 获取服务端IP
                            let server_ip = stream.local_addr().unwrap().ip().to_string();

                            let scheme = if config_new.https {
                                match acceptor_new.accept(stream.try_clone().unwrap()) {
                                    Ok(e) => Scheme::Https(e, client_ip.clone()),
                                    Err(_) => return,
                                }
                            } else {
                                Scheme::Http(stream.try_clone().unwrap(), client_ip.clone())
                            };

                            let mut client = Client {
                                config: config_new.clone(),
                                request: Request::default(config_new.root_path.clone()),
                                response: Response::default(config_new.root_path),
                                server_ip,
                                client_ip,
                                factory,
                                proxy_ip: String::new(),
                            };
                            match client.handle_service(scheme) {
                                Ok(()) => {}
                                Err(e) => error!("{e}"),
                            }
                        });
                    }
                    Err(e) => return Err(e),
                }
            }
        }
        Ok(())
    }

    #[cfg(feature = "webpage")]
    /// 网页服务器
    pub fn new_webpage(config: &Config, factory: fn(config: Config) -> Box<dyn Handler>) {
        loop {
            match WebServer::webpage(&config.clone(), factory) {
                Ok(()) => {}
                Err(e) => error!("{}[{}]: {}", file!(), line!(), e),
            }
            warn!("服务器 2秒后重启");
            thread::sleep(Duration::from_secs(2));
        }
    }
    #[cfg(feature = "webpage")]
    fn webpage(config: &Config, factory: fn(config: Config) -> Box<dyn Handler>) -> io::Result<()> {
        info!("==================== 网页服务 服务信息 ====================");
        info!(
            "日志记录: {}",
            if config.is_save_log {
                "开启"
            } else {
                "关闭"
            }
        );
        info!(
            "调试模式: {}",
            if config.is_debug { "开启" } else { "关闭" }
        );
        info!("地    址: {}", config.host);
        info!("端 口 号: {}", config.port);
        info!(
            "服务地址: {}://{}{}",
                if config.https { "https" } else { "http" },
                config.host,
                if config.port > 0 {
                    format!(":{}", config.port)
                } else {
                    String::new()
                }
        );
        info!("网页目录: {}", config.public);
        info!(
            "SSL/TLS: {}",
            if config.https { "开启" } else { "关闭" }
        );
        if config.https {
            info!("证书目录KEY: {:?}", config.tls.key);
            info!("证书目录PEM: {:?}", config.tls.certs);
        }

        let addrs = [SocketAddr::from((
            IpAddr::V4(config.host.parse().unwrap()),
            config.port,
        ))];
        let listener = TcpListener::bind(&addrs[..])?;
        info!("==================== 网页服务 启动成功 ====================");


        let acceptor = Self::ssl(&config.clone())?;
        for stream in listener.incoming() {
            match stream {
                Ok(stream) => {
                    let config_new = config.clone();
                    let acceptor = acceptor.clone();

                    thread::spawn(move || {
                        // 设置超时时间
                        if config_new.write_timeout > 0 {
                            stream.set_write_timeout(Some(Duration::from_secs(
                                config_new.write_timeout,
                            ))).unwrap_or_default();
                        }
                        if config_new.read_timeout > 0 {
                            stream.set_read_timeout(Some(Duration::from_secs(
                                config_new.read_timeout,
                            ))).unwrap_or_default();
                        }

                        // 获取请求客户端IP
                        let client_ip = stream.peer_addr().unwrap().to_string();
                        // 获取服务端IP
                        let server_ip = stream.local_addr().unwrap().to_string();

                        let scheme = if config_new.https {
                            match acceptor.accept(stream.try_clone().unwrap()) {
                                Ok(e) => Scheme::Https(e, client_ip.clone()),
                                Err(_) => return,
                            }
                        } else {
                            Scheme::Http(stream.try_clone().unwrap(), client_ip.clone())
                        };
                        let client = Client {
                            config: config_new.clone(),
                            request: Request::default(config_new.root_path.clone()),
                            response: Response::default(config_new.root_path.clone()),
                            factory,
                            server_ip,
                            client_ip,
                            proxy_ip: String::new(),
                        };
                        match client.handle_webpage(scheme) {
                            Ok(()) => {}
                            Err(e) => error!("{e}"),
                        }
                    });
                }
                Err(e) => return Err(e),
            }
        }
        Ok(())
    }

    fn ssl(config: &Config) -> io::Result<Arc<SslAcceptor>> {
        if config.https {
            let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls())?;
            if !config.tls.key.is_file() {
                return Err(Error::other(
                    format!("private.key 不存在: {:?}", config.tls.key).as_str(),
                ));
            }
            if !config.tls.certs.is_file() {
                return Err(Error::other(
                    format!("certificate.pem 不存在: {:?}", config.tls.certs).as_str(),
                ));
            }
            acceptor.set_private_key_file(config.tls.key.clone(), SslFiletype::PEM)?;
            acceptor.set_certificate_file(config.tls.certs.clone(), SslFiletype::PEM)?;
            Ok(Arc::new(acceptor.build()))
        } else {
            Ok(Arc::new(SslAcceptor::mozilla_intermediate(SslMethod::tls())?.build()))
        }
    }
}

pub trait Handler {
    /// 请求 处理
    #[cfg(any(feature = "webpage", feature = "service"))]
    fn on_request(&mut self, request: Request, response: Response) -> Response;
    #[cfg(any(feature = "webpage", feature = "service"))]
    /// 预检请求处理 OPTIONS
    fn on_options(&mut self, _request: Request, mut response: Response) -> Response {
        response.header("Access-Control-Allow-Origin", "*");
        // GET,POST,OPTIONS
        response.header("Access-Control-Allow-Methods", "*");
        // Content-Type, Authorization, X-Real-IP,X-Forwarded-For
        response.header("Access-Control-Allow-Headers", "*");
        response.header("Access-Control-Allow-Credentials", "true");
        response.header("Access-Control-Expose-Headers", "content-disposition");
        response.header("Access-Control-Max-Age", "0");
        response
    }
    #[cfg(any(feature = "service", feature = "webpage"))]
    /// 响应 处理
    fn on_response(&mut self, request: Request, mut response: Response) -> Response {
        if response.config.origin.is_empty() {
            response.header("Access-Control-Allow-Origin", "*");
        } else {
            let origin = request.header["origin"].as_str().unwrap_or("");
            if !origin.is_empty() && response.config.origin.contains(&origin.to_string().clone()) {
                response.header("Access-Control-Allow-Origin", origin);
            }
        }
        if response.headers.has_key("Content-Disposition") {
            response.header("Access-Control-Expose-Headers", "content-disposition");
        }
        response
    }
    /// 握手监听
    fn on_open(&mut self, _websocket: Websocket) -> io::Result<()> {
        Ok(())
    }
    /// 接收到消息
    fn on_message(&mut self, _msg: Message) -> io::Result<()> {
        Ok(())
    }
    /// 关闭监听
    fn on_close(&mut self, _code: CloseCode, _reason: &str) {}
    /// 错误监听
    fn on_error(&mut self, _err: ErrorCode) {}
    /// 关机监听
    fn on_shutdown(&mut self) {}
    /// ping
    fn on_ping(&mut self, _msg: Message) {}
    /// pong
    fn on_pong(&mut self, _msg: Message) {}
}