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