br_web_server/
lib.rs

1mod stream;
2pub mod config;
3pub mod request;
4pub mod response;
5pub mod websocket;
6#[cfg(feature = "pools")]
7mod pools;
8use crate::stream::{Scheme};
9use crate::config::{Config};
10use crate::request::{Request};
11use crate::response::Response;
12use crate::websocket::{CloseCode, ErrorCode, Message, Websocket};
13use log::{error, info, warn};
14#[cfg(feature = "https")]
15use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
16use std::io::{Error, Write};
17use std::net::{TcpListener};
18use std::sync::{Arc, Mutex};
19use std::time::{Duration};
20use std::{io, thread};
21use std::fmt::Debug;
22use std::path::PathBuf;
23use flate2::Compression;
24use flate2::write::GzEncoder;
25use json::{object, JsonValue};
26
27/// 网络服务
28#[derive(Clone, Debug)]
29pub struct WebServer;
30
31impl WebServer {
32    /// 后台服务器
33    pub fn new_service(config: Config, factory: fn(out: Websocket) -> Box<dyn Handler>) {
34        loop {
35            match WebServer::service(config.clone(), factory) {
36                Ok(()) => {}
37                Err(e) => error!("服务器错误: {}[{}]: {}", file!(), line!(), e),
38            }
39            warn!("服务器 1秒后重启");
40            thread::sleep(Duration::from_secs(1));
41        }
42    }
43    fn service(config: Config, factory: fn(out: Websocket) -> Box<dyn Handler>) -> io::Result<()> {
44        info!("==================== 网络服务 服务信息 ====================");
45        info!("日志记录: {}",if config.log {"开启"} else {"关闭"});
46        info!("调试模式: {}",if config.debug { "开启" } else { "关闭" });
47        info!("监听地址: {}", config.host);
48        info!("服务地址: {}://{}",if config.https { "https" } else { "http" },config.host);
49        info!("根 目 录: {}", config.root_path.to_str().unwrap());
50        info!("访问目录: {}", config.public);
51        info!("运行目录: {}", config.runtime);
52        info!("SSL/TLS: {}",if config.https { "开启" } else { "关闭" });
53
54        if config.https {
55            info!("证书目录KEY: {:?}", config.tls.key);
56            info!("证书目录PEM: {:?}", config.tls.certs);
57        }
58
59        let listener = TcpListener::bind(config.host.clone())?;
60        info!("==================== 网络服务 启动成功 ====================");
61
62        #[cfg(feature = "https")] let acceptor = Self::ssl(config.clone())?;
63        #[cfg(feature = "pools")] let mut pool = pools::Pool::new(config.pools_max * 4);
64        for stream in listener.incoming() {
65            match stream {
66                Ok(stream) => {
67                    let config_new = config.clone();
68                    #[cfg(feature = "https")] let acceptor_new = acceptor.clone();
69                    #[cfg(not(feature = "pools"))]
70                    thread::spawn(move || -> io::Result<()> {
71                        stream.set_nonblocking(false)?;
72                        // 设置读取超时时间
73                        stream.set_read_timeout(Some(Duration::from_secs(30))).unwrap_or_default();
74                        // 设置发送超时时间
75                        stream.set_write_timeout(Some(Duration::from_secs(30))).unwrap_or_default();
76                        #[cfg(feature = "https")]
77                        {
78                            let scheme = if config_new.https {
79                                match acceptor_new.accept(stream) {
80                                    Ok(e) => Scheme::Https(Arc::new(Mutex::new(e))),
81                                    Err(_) => return Err(Error::other("加载加密请求失败")),
82                                }
83                            } else {
84                                Scheme::Http(Arc::new(Mutex::new(stream)))
85                            };
86                        }
87                        #[cfg(not(feature = "https"))] let scheme = Scheme::Http(Arc::new(Mutex::new(stream)));
88
89                        let mut request = Request::new(config_new.clone(), Arc::new(Mutex::new(scheme.clone())));
90                        let response = match request.handle() {
91                            Ok(()) => Response::new(&request.clone(), factory),
92                            Err(e) => {
93                                //error!("处理请求: {:?} {} {}",thread::current().id() ,e.code, e.body);
94                                return Err(Error::other(e.body.as_str()));
95                            }
96                        };
97                        match response.handle() {
98                            Ok(()) => {}
99                            Err(e) => {
100                                //error!("发送错误失败2: {}",e.to_string());
101                                return Err(Error::other(e));
102                            }
103                        };
104
105                        match request.save_log() {
106                            Ok(()) => {}
107                            Err(_) => error!("日志记录错误")
108                        }
109                        Ok(())
110                    });
111
112                    #[cfg(feature = "pools")]
113                    pool.execute(move || -> io::Result<()> {
114
115                        // 设置读取超时时间
116                        stream.set_read_timeout(Some(Duration::from_secs(15))).unwrap_or_default();
117                        // 设置发送超时时间
118                        stream.set_write_timeout(Some(Duration::from_secs(15))).unwrap_or_default();
119
120                        let scheme = if config_new.https {
121                            match acceptor_new.accept(stream) {
122                                Ok(e) => Scheme::Https(Arc::new(Mutex::new(e))),
123                                Err(_) => return Err(Error::other("加载加密请求失败")),
124                            }
125                        } else {
126                            Scheme::Http(Arc::new(Mutex::new(stream)))
127                        };
128                        let mut request = Request::new(config_new.clone(), Arc::new(Mutex::new(scheme.clone())));
129                        let request_req = request.handle();
130                        let mut response = Response::new(&request.clone(), factory);
131                        match request_req {
132                            Ok(()) => {}
133                            Err(e) => return match response.status(e.code).txt(e.body.as_str()).send() {
134                                Ok(()) => Ok(()),
135                                Err(e) => Err(Error::other(e.body.as_str())),
136                            }
137                        };
138                        response.handle()?;
139                        match request.save_log() {
140                            Ok(()) => {}
141                            Err(_) => {
142                                error!("日志记录错误");
143                            }
144                        }
145                        Ok(())
146                    });
147                }
148                Err(e) => return Err(e),
149            }
150        }
151        #[cfg(feature = "pools")]
152        pool.end();
153        Ok(())
154    }
155
156    #[cfg(feature = "https")]
157    fn ssl(config: Config) -> io::Result<Arc<SslAcceptor>> {
158        if config.https {
159            let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls())?;
160            if !config.tls.key.is_file() {
161                return Err(Error::other(
162                    format!("private.key 不存在: {:?}", config.tls.key).as_str(),
163                ));
164            }
165            if !config.tls.certs.is_file() {
166                return Err(Error::other(
167                    format!("certificate.pem 不存在: {:?}", config.tls.certs).as_str(),
168                ));
169            }
170            acceptor.set_private_key_file(config.tls.key.clone(), SslFiletype::PEM)?;
171            acceptor.set_certificate_file(config.tls.certs.clone(), SslFiletype::PEM)?;
172            Ok(Arc::new(acceptor.build()))
173        } else {
174            Ok(Arc::new(SslAcceptor::mozilla_intermediate(SslMethod::tls())?.build()))
175        }
176    }
177}
178
179pub trait HandlerClone {
180    fn clone_box(&self) -> Box<dyn Handler>;
181}
182
183/// 实现 HandlerClone for 所有 Handler + Clone 的实现者
184impl<T> HandlerClone for T
185where
186    T: 'static + Handler + Clone,
187{
188    fn clone_box(&self) -> Box<dyn Handler> {
189        Box::new(self.clone())
190    }
191}
192
193// 为 dyn Handler 实现 Clone
194impl Clone for Box<dyn Handler> {
195    fn clone(&self) -> Box<dyn Handler> {
196        self.clone_box()
197    }
198}
199pub trait Handler: Send + Sync + HandlerClone + Debug {
200    /// 请求 处理
201    fn on_request(&mut self, _request: Request, _response: &mut Response);
202    /// 预检请求处理 OPTIONS
203    fn on_options(&mut self, response: &mut Response) {
204        response.allow_origins = vec![];
205        response.allow_methods = vec!["GET", "POST", "PUT", "DELETE", "OPTIONS"];
206        response.allow_headers = vec!["Authorization", "X-Forwarded-For", "X-Real-IP"];
207        response.header("Access-Control-Expose-Headers", "Content-Disposition");
208        response.header("Access-Control-Max-Age", 86400.to_string().as_str());
209    }
210    /// 响应 处理
211    fn on_response(&mut self, response: &mut Response) {
212        if !response.headers.has_key("Access-Control-Allow-Origin") {
213            response.header("Access-Control-Allow-Origin", "*");
214        }
215        // 允许前端跨域请求时发送和接收 cookie / 凭据
216        if !response.headers.has_key("Access-Control-Allow-Credentials") {
217            response.header("Access-Control-Allow-Credentials", "true");
218        }
219        //// 允许前端读取指定请求头
220        //if !response.headers.has_key("Access-Control-Expose-Headers") {
221        //    response.header("Access-Control-Expose-Headers", "Content-Disposition");
222        //}
223    }
224
225    fn on_frame(&mut self) -> Result<(), HttpError> {
226        Ok(())
227    }
228    /// 握手监听
229    fn on_open(&mut self) -> Result<(), HttpError> {
230        Ok(())
231    }
232    /// 接收到消息
233    fn on_message(&mut self, _msg: Message) -> Result<(), HttpError> {
234        Ok(())
235    }
236    /// 关闭监听
237    fn on_close(&mut self, _code: CloseCode, _reason: &str) {}
238    /// 错误监听
239    fn on_error(&mut self, _err: ErrorCode) {}
240    /// 关机监听
241    fn on_shutdown(&mut self) {}
242}
243
244
245#[derive(Clone, Debug)]
246pub enum Connection {
247    /// 长连接
248    KeepAlive,
249    /// 短连接
250    Close,
251    Other(String),
252}
253impl Connection {
254    fn from(value: &str) -> Self {
255        match value.to_lowercase().as_str() {
256            "keep-alive" => Self::KeepAlive,
257            "close" => Self::Close,
258            _ => Self::Other(value.to_string()),
259        }
260    }
261    pub fn str(&self) -> &str {
262        match self {
263            Connection::KeepAlive => "keep-alive",
264            Connection::Close => "close",
265            Connection::Other(name) => name
266        }
267    }
268}
269#[derive(Clone, Debug)]
270pub enum Upgrade {
271    Websocket,
272    Http,
273    H2c,
274    Other(String),
275}
276impl Upgrade {
277    fn from(name: &str) -> Self {
278        match name.to_lowercase().as_str() {
279            "websocket" => Upgrade::Websocket,
280            "http" => Upgrade::Http,
281            "h2c" => Upgrade::H2c,
282            _ => Upgrade::Other(name.to_lowercase().as_str().to_string()),
283        }
284    }
285    pub fn str(&self) -> &str {
286        match self {
287            Upgrade::Websocket => "websocket",
288            Upgrade::Http => "http",
289            Upgrade::H2c => "h2c",
290            Upgrade::Other(name) => name,
291        }
292    }
293}
294
295/// 统一资源标识符
296#[derive(Clone, Debug)]
297#[derive(Default)]
298pub struct Uri {
299    /// 资源标识
300    pub uri: String,
301    /// 完整 url
302    pub url: String,
303    /// 查询字符串
304    pub query: String,
305    /// 片段或位置
306    pub fragment: String,
307    /// 资源路径
308    pub path: String,
309    /// 资源段落
310    pub path_segments: Vec<String>,
311}
312impl Uri {
313    pub fn from(url: &str) -> Self {
314        let mut decoded_url = br_crypto::encoding::urlencoding_decode(url);
315        let fragment = match decoded_url.rfind('#') {
316            None => String::new(),
317            Some(index) => decoded_url.drain(index..).collect::<String>(),
318        };
319
320        let query = match decoded_url.rfind('?') {
321            None => String::new(),
322            Some(index) => decoded_url.drain(index..).collect::<String>().trim_start_matches("?").to_string(),
323        };
324
325        let path_segments = decoded_url.split('/').map(|x| x.to_string()).filter(|x| !x.is_empty()).collect::<Vec<String>>();
326        Self {
327            uri: decoded_url.clone(),
328            url: url.to_string(),
329            query,
330            fragment,
331            path: decoded_url.clone(),
332            path_segments,
333        }
334    }
335    /// 获取请求参数
336    #[must_use]
337    pub fn get_query_params(&self) -> JsonValue {
338        let text = self.query.split('&').collect::<Vec<&str>>();
339        let mut params = object! {};
340        for item in text {
341            if let Some(index) = item.find('=') {
342                let key = item[..index].to_string();
343                let value = item[index + 1..].to_string();
344                let _ = params.insert(key.as_str(), value);
345            }
346        }
347        params
348    }
349    #[must_use]
350    pub fn to_json(&self) -> JsonValue {
351        object! {
352            url: self.url.clone(),
353            query: self.query.clone(),
354            fragment: self.fragment.clone(),
355            path: self.path.clone(),
356            path_segments: self.path_segments.clone()
357        }
358    }
359}
360
361
362/// 请求方法
363#[derive(Clone, Debug)]
364pub enum Method {
365    /// 请求
366    POST,
367    /// 获取
368    GET,
369    /// 请求头
370    HEAD,
371    /// 更新
372    PUT,
373    /// 删除
374    DELETE,
375    /// 预请求
376    OPTIONS,
377    PATCH,
378    TRACE,
379    VIEW,
380    CONNECT,
381    PROPFIND,
382    /// http2.0
383    PRI,
384    /// 其他
385    Other(String),
386}
387
388impl Method {
389    #[must_use]
390    pub fn from(name: &str) -> Self {
391        match name.to_lowercase().as_str() {
392            "post" => Self::POST,
393            "get" => Self::GET,
394            "head" => Self::HEAD,
395            "put" => Self::PUT,
396            "delete" => Self::DELETE,
397            "options" => Self::OPTIONS,
398            "patch" => Self::PATCH,
399            "trace" => Self::TRACE,
400            "view" => Self::VIEW,
401            "propfind" => Self::PROPFIND,
402            "connect" => Self::CONNECT,
403            "pri" => Self::PRI,
404            _ => Self::Other(name.to_string()),
405        }
406    }
407    pub fn str(&mut self) -> &str {
408        match self {
409            Method::POST => "POST",
410            Method::GET => "GET",
411            Method::HEAD => "HEAD",
412            Method::PUT => "PUT",
413            Method::DELETE => "DELETE",
414            Method::OPTIONS => "OPTIONS",
415            Method::PATCH => "PATCH",
416            Method::TRACE => "TRACE",
417            Method::VIEW => "VIEW",
418            Method::PROPFIND => "PROPFIND",
419            Method::PRI => "PRI",
420            Method::CONNECT => "CONNECT",
421            Method::Other(e) => e
422        }
423    }
424}
425
426#[derive(Debug, Clone)]
427pub struct HttpError {
428    pub code: u16,
429    pub body: String,
430}
431
432impl HttpError {
433    /// 构造函数:用状态码和文本信息
434    #[must_use]
435    pub fn new(code: u16, body: &str) -> Self {
436        Self {
437            code,
438            body: body.to_string(),
439        }
440    }
441}
442/// 内容类型
443#[derive(Debug, Clone)]
444pub enum ContentType {
445    FormData,
446    FormUrlencoded,
447    Json,
448    Xml,
449    Javascript,
450    Text,
451    Html,
452    Stream,
453    Other(String),
454}
455impl ContentType {
456    #[must_use]
457    pub fn from(name: &str) -> Self {
458        match name {
459            "multipart/form-data" => Self::FormData,
460            "application/x-www-form-urlencoded" => Self::FormUrlencoded,
461            "application/json" => Self::Json,
462            "application/xml" | "text/xml" => Self::Xml,
463            "application/javascript" => Self::Javascript,
464            "application/octet-stream" => Self::Stream,
465            "text/html" => Self::Html,
466            "text/plain" => Self::Text,
467            _ => Self::Other(name.to_string()),
468        }
469    }
470    #[must_use]
471    pub fn str(&self) -> &str {
472        match self {
473            ContentType::FormData => "multipart/form-data",
474            ContentType::FormUrlencoded => "application/x-www-form-urlencoded",
475            ContentType::Json => "application/json",
476            ContentType::Xml => "application/xml",
477            ContentType::Javascript => "application/javascript",
478            ContentType::Text => "text/plain",
479            ContentType::Html => "text/html",
480            ContentType::Other(name) => name.as_str(),
481            ContentType::Stream => "application/octet-stream"
482        }
483    }
484}
485/// 认证
486#[derive(Clone, Debug)]
487pub enum Authorization {
488    Basic(String, String),
489    Bearer(String),
490    Digest(JsonValue),
491    Other(String),
492}
493impl Authorization {
494    #[must_use]
495    pub fn from(data: &str) -> Self {
496        let authorization = data.split_whitespace().collect::<Vec<&str>>();
497        let mode = authorization[0].to_lowercase();
498        match mode.as_str() {
499            "basic" => {
500                let text = br_crypto::base64::decode(&authorization[1].to_string().clone());
501                let text: Vec<&str> = text.split(':').collect();
502                Self::Basic(text[0].to_string(), text[1].to_string())
503            }
504            "bearer" => Self::Bearer(authorization[1].to_string()),
505            "digest" => {
506                let text = authorization[1..].concat().clone();
507                let text = text.split(',').collect::<Vec<&str>>();
508                let mut params = object! {};
509                for item in &text {
510                    let Some(index) = item.find('=') else { continue };
511                    let key = item[..index].to_string();
512                    let value = item[index + 2..item.len() - 1].to_string();
513                    let _ = params.insert(key.as_str(), value);
514                }
515                Self::Digest(params)
516            }
517            _ => Self::Other(data.to_string())
518        }
519    }
520    pub fn str(&mut self) -> JsonValue {
521        match self {
522            Authorization::Basic(key, value) => {
523                let mut data = object! {};
524                data[key.as_str()] = value.clone().into();
525                data
526            }
527            Authorization::Bearer(e) => e.clone().into(),
528            Authorization::Digest(e) => e.clone(),
529            Authorization::Other(name) => name.clone().into(),
530        }
531    }
532}
533/// 消息内容
534#[derive(Clone, Debug)]
535pub enum Content {
536    FormUrlencoded(JsonValue),
537    FormData(JsonValue),
538    Json(JsonValue),
539    Text(JsonValue),
540    Xml(JsonValue),
541    None,
542}
543impl Content {}
544#[derive(Clone, Debug)]
545pub enum FormData {
546    File(String, PathBuf),
547    Field(JsonValue),
548}
549
550/// 语言
551#[derive(Clone, Debug)]
552pub enum Language {
553    ZhCN,
554    ZhHans,
555    En,
556    Other(String),
557
558}
559impl Language {
560    #[must_use]
561    pub fn from(name: &str) -> Self {
562        let binding = name.split(',').collect::<Vec<&str>>()[0].trim().to_lowercase();
563        let name = binding.as_str();
564        match name {
565            "zh-cn" => Self::ZhCN,
566            "zh-hans" => Self::ZhHans,
567            "en" => Self::En,
568            _ => Self::Other(name.to_string()),
569        }
570    }
571    #[must_use]
572    pub fn str(&self) -> &str {
573        match self {
574            Language::ZhCN => "zh-CN",
575            Language::ZhHans => "zh-Hans",
576            Language::En => "en",
577            Language::Other(e) => e.as_str(),
578        }
579    }
580}
581
582
583/// 压缩方式
584#[derive(Clone, Debug)]
585pub enum Encoding {
586    Gzip,
587    Deflate,
588    Br,
589    Bzip2,
590    None,
591}
592impl Encoding {
593    #[must_use]
594    pub fn from(s: &str) -> Encoding {
595        match s.to_lowercase().as_str() {
596            x if x.contains("gzip") => Encoding::Gzip,
597            x if x.contains("deflate") => Encoding::Deflate,
598            x if x.contains("br") => Encoding::Br,
599            x if x.contains("bzip2") => Encoding::Bzip2,
600            _ => Encoding::None,
601        }
602    }
603    #[must_use]
604    pub fn str(&self) -> &str {
605        match self {
606            Encoding::Gzip => "gzip",
607            Encoding::Deflate => "deflate",
608            Encoding::Br => "br",
609            Encoding::None => "",
610            Encoding::Bzip2 => "bzip2",
611        }
612    }
613    pub fn compress(self, data: &[u8]) -> io::Result<Vec<u8>> {
614        match self {
615            Encoding::Gzip => {
616                let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
617                encoder.write_all(data)?;
618                encoder.finish()
619            }
620            _ => Ok(data.to_vec()),
621        }
622    }
623}