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 || {
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                        loop {
90                            let mut request = Request::new(config_new.clone(), Arc::new(Mutex::new(scheme.clone())));
91                            let response = match request.handle() {
92                                Ok(()) => Response::new(request.clone(), factory),
93                                Err(e) => {
94                                    //error!("处理请求: {:?} {} {}",thread::current().id() ,e.code, e.body);
95                                    return Err(Error::other(e.body.as_str()));
96                                }
97                            };
98                            match response.handle() {
99                                Ok(()) => {}
100                                Err(e) => {
101                                    error!("发送错误失败2: {}",e.to_string());
102                                    return Err(Error::other(e));
103                                }
104                            };
105                            match request.upgrade {
106                                Upgrade::H2c => continue,
107                                _ => {}
108                            }
109                            match request.save_log() {
110                                Ok(()) => {}
111                                Err(_) => error!("日志记录错误")
112                            }
113                            break Ok(());
114                        }
115                    });
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                        let scheme = if config_new.https {
126                            match acceptor_new.accept(stream) {
127                                Ok(e) => Scheme::Https(Arc::new(Mutex::new(e))),
128                                Err(_) => return Err(Error::other("加载加密请求失败")),
129                            }
130                        } else {
131                            Scheme::Http(Arc::new(Mutex::new(stream)))
132                        };
133                        let mut request = Request::new(config_new.clone(), Arc::new(Mutex::new(scheme.clone())));
134                        let request_req = request.handle();
135                        let mut response = Response::new(request.clone(), factory);
136                        match request_req {
137                            Ok(()) => {}
138                            Err(e) => return match response.status(e.code).txt(e.body.as_str()).send() {
139                                Ok(()) => Ok(()),
140                                Err(e) => Err(Error::other(e.body.as_str())),
141                            }
142                        };
143                        response.handle()?;
144                        match request.save_log() {
145                            Ok(()) => {}
146                            Err(_) => {
147                                error!("日志记录错误");
148                            }
149                        }
150                        Ok(())
151                    });
152                }
153                Err(e) => return Err(e),
154            }
155        }
156        #[cfg(feature = "pools")]
157        pool.end();
158        Ok(())
159    }
160
161    #[cfg(feature = "https")]
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, response: &mut Response) {
217        if !response.headers.has_key("Access-Control-Allow-Origin") {
218            response.header("Access-Control-Allow-Origin", "*");
219        }
220        // 允许前端跨域请求时发送和接收 cookie / 凭据
221        if !response.headers.has_key("Access-Control-Allow-Credentials") {
222            response.header("Access-Control-Allow-Credentials", "true");
223        }
224        //// 允许前端读取指定请求头
225        //if !response.headers.has_key("Access-Control-Expose-Headers") {
226        //    response.header("Access-Control-Expose-Headers", "Content-Disposition");
227        //}
228    }
229
230    fn on_frame(&mut self) -> Result<(), HttpError> {
231        Ok(())
232    }
233    /// 握手监听
234    fn on_open(&mut self) -> Result<(), HttpError> {
235        Ok(())
236    }
237    /// 接收到消息
238    fn on_message(&mut self, _msg: Message) -> Result<(), HttpError> {
239        Ok(())
240    }
241    /// 关闭监听
242    fn on_close(&mut self, _code: CloseCode, _reason: &str) {}
243    /// 错误监听
244    fn on_error(&mut self, _err: ErrorCode) {}
245    /// 关机监听
246    fn on_shutdown(&mut self) {}
247}
248
249
250#[derive(Clone, Debug)]
251pub enum Connection {
252    /// 长连接
253    KeepAlive,
254    /// 短连接
255    Close,
256    Other(String),
257}
258impl Connection {
259    fn from(value: &str) -> Self {
260        match value.to_lowercase().as_str() {
261            "keep-alive" => Self::KeepAlive,
262            "close" => Self::Close,
263            _ => Self::Other(value.to_string()),
264        }
265    }
266    pub fn str(&self) -> &str {
267        match self {
268            Connection::KeepAlive => "keep-alive",
269            Connection::Close => "close",
270            Connection::Other(name) => name
271        }
272    }
273}
274#[derive(Clone, Debug)]
275pub enum Upgrade {
276    Websocket,
277    Http,
278    H2c,
279    Other(String),
280}
281impl Upgrade {
282    fn from(name: &str) -> Self {
283        match name.to_lowercase().as_str() {
284            "websocket" => Upgrade::Websocket,
285            "http" => Upgrade::Http,
286            "h2c" => Upgrade::H2c,
287            _ => Upgrade::Other(name.to_lowercase().as_str().to_string()),
288        }
289    }
290    pub fn str(&self) -> &str {
291        match self {
292            Upgrade::Websocket => "websocket",
293            Upgrade::Http => "http",
294            Upgrade::H2c => "h2c",
295            Upgrade::Other(name) => name,
296        }
297    }
298}
299
300/// 统一资源标识符
301#[derive(Clone, Debug)]
302#[derive(Default)]
303pub struct Uri {
304    /// 资源标识
305    pub uri: String,
306    /// 完整 url
307    pub url: String,
308    /// 查询字符串
309    pub query: String,
310    /// 片段或位置
311    pub fragment: String,
312    /// 资源路径
313    pub path: String,
314    /// 资源段落
315    pub path_segments: Vec<String>,
316}
317impl Uri {
318    pub fn from(url: &str) -> Self {
319        let mut decoded_url = br_crypto::encoding::urlencoding_decode(url);
320        let fragment = match decoded_url.rfind('#') {
321            None => String::new(),
322            Some(index) => decoded_url.drain(index..).collect::<String>(),
323        };
324
325        let query = match decoded_url.rfind('?') {
326            None => String::new(),
327            Some(index) => decoded_url.drain(index..).collect::<String>().trim_start_matches("?").to_string(),
328        };
329
330        let path_segments = decoded_url.split("/").map(|x| x.to_string()).filter(|x| !x.is_empty()).collect::<Vec<String>>();
331        Self {
332            uri: decoded_url.clone(),
333            url: url.to_string(),
334            query,
335            fragment,
336            path: decoded_url.clone(),
337            path_segments,
338        }
339    }
340    /// 获取请求参数
341    pub fn get_query_params(&self) -> JsonValue {
342        let text = self.query.split('&').collect::<Vec<&str>>();
343        let mut params = object! {};
344        for item in text {
345            if let Some(index) = item.find('=') {
346                let key = item[..index].to_string();
347                let value = item[index + 1..].to_string();
348                let _ = params.insert(key.as_str(), value);
349            }
350        }
351        params
352    }
353    #[must_use]
354    pub fn to_json(&self) -> JsonValue {
355        object! {
356            url: self.url.clone(),
357            query: self.query.clone(),
358            fragment: self.fragment.clone(),
359            path: self.path.clone(),
360            path_segments: self.path_segments.clone()
361        }
362    }
363}
364
365
366/// 请求方法
367#[derive(Clone, Debug)]
368pub enum Method {
369    /// 请求
370    POST,
371    /// 获取
372    GET,
373    /// 请求头
374    HEAD,
375    /// 更新
376    PUT,
377    /// 删除
378    DELETE,
379    /// 预请求
380    OPTIONS,
381    PATCH,
382    TRACE,
383    VIEW,
384    CONNECT,
385    PROPFIND,
386    /// http2.0
387    PRI,
388    /// 其他
389    Other(String),
390}
391
392impl Method {
393    #[must_use]
394    pub fn from(name: &str) -> Self {
395        match name.to_lowercase().as_str() {
396            "post" => Self::POST,
397            "get" => Self::GET,
398            "head" => Self::HEAD,
399            "put" => Self::PUT,
400            "delete" => Self::DELETE,
401            "options" => Self::OPTIONS,
402            "patch" => Self::PATCH,
403            "trace" => Self::TRACE,
404            "view" => Self::VIEW,
405            "propfind" => Self::PROPFIND,
406            "connect" => Self::CONNECT,
407            "pri" => Self::PRI,
408            _ => Self::Other(name.to_string()),
409        }
410    }
411    pub fn str(&mut self) -> &str {
412        match self {
413            Method::POST => "POST",
414            Method::GET => "GET",
415            Method::HEAD => "HEAD",
416            Method::PUT => "PUT",
417            Method::DELETE => "DELETE",
418            Method::OPTIONS => "OPTIONS",
419            Method::PATCH => "PATCH",
420            Method::TRACE => "TRACE",
421            Method::VIEW => "VIEW",
422            Method::PROPFIND => "PROPFIND",
423            Method::PRI => "PRI",
424            Method::CONNECT => "CONNECT",
425            Method::Other(e) => e
426        }
427    }
428}
429
430#[derive(Debug, Clone)]
431pub struct HttpError {
432    pub code: u16,
433    pub body: String,
434}
435
436impl HttpError {
437    /// 构造函数:用状态码和文本信息
438    pub fn new(code: u16, body: &str) -> Self {
439        Self {
440            code,
441            body: body.to_string(),
442        }
443    }
444}
445/// 内容类型
446#[derive(Debug, Clone)]
447pub enum ContentType {
448    FormData,
449    FormUrlencoded,
450    Json,
451    Xml,
452    Javascript,
453    Text,
454    Html,
455    Stream,
456    Other(String),
457}
458impl ContentType {
459    pub fn from(name: &str) -> Self {
460        match name {
461            "multipart/form-data" => Self::FormData,
462            "application/x-www-form-urlencoded" => Self::FormUrlencoded,
463            "application/json" => Self::Json,
464            "application/xml" | "text/xml" => Self::Xml,
465            "application/javascript" => Self::Javascript,
466            "application/octet-stream" => Self::Stream,
467            "text/html" => Self::Html,
468            "text/plain" => Self::Text,
469            _ => Self::Other(name.to_string()),
470        }
471    }
472    pub fn str(&self) -> &str {
473        match self {
474            ContentType::FormData => "multipart/form-data",
475            ContentType::FormUrlencoded => "application/x-www-form-urlencoded",
476            ContentType::Json => "application/json",
477            ContentType::Xml => "application/xml",
478            ContentType::Javascript => "application/javascript",
479            ContentType::Text => "text/plain",
480            ContentType::Html => "text/html",
481            ContentType::Other(name) => name.as_str(),
482            ContentType::Stream => "application/octet-stream"
483        }
484    }
485}
486/// 认证
487#[derive(Clone, Debug)]
488pub enum Authorization {
489    Basic(String, String),
490    Bearer(String),
491    Digest(JsonValue),
492    Other(String),
493}
494impl Authorization {
495    #[must_use]
496    pub fn from(data: &str) -> Self {
497        let authorization = data.split_whitespace().collect::<Vec<&str>>();
498        let mode = authorization[0].to_lowercase();
499        match mode.as_str() {
500            "basic" => {
501                let text = br_crypto::base64::decode(&authorization[1].to_string().clone());
502                let text: Vec<&str> = text.split(':').collect();
503                Self::Basic(text[0].to_string(), text[1].to_string())
504            }
505            "bearer" => Self::Bearer(authorization[1].to_string()),
506            "digest" => {
507                let text = authorization[1..].concat().clone();
508                let text = text.split(',').collect::<Vec<&str>>();
509                let mut params = object! {};
510                for item in &text {
511                    let Some(index) = item.find('=') else { continue };
512                    let key = item[..index].to_string();
513                    let value = item[index + 2..item.len() - 1].to_string();
514                    let _ = params.insert(key.as_str(), value);
515                }
516                Self::Digest(params)
517            }
518            _ => Self::Other(data.to_string())
519        }
520    }
521    pub fn str(&mut self) -> JsonValue {
522        match self {
523            Authorization::Basic(key, value) => {
524                let mut data = object! {};
525                data[key.as_str()] = value.clone().into();
526                data
527            }
528            Authorization::Bearer(e) => e.clone().into(),
529            Authorization::Digest(e) => e.clone(),
530            Authorization::Other(name) => name.clone().into(),
531        }
532    }
533}
534/// 消息内容
535#[derive(Clone, Debug)]
536pub enum Content {
537    FormUrlencoded(JsonValue),
538    FormData(JsonValue),
539    Json(JsonValue),
540    Text(JsonValue),
541    Xml(JsonValue),
542    None,
543}
544impl Content {}
545#[derive(Clone, Debug)]
546pub enum FormData {
547    File(String, PathBuf),
548    Field(JsonValue),
549}
550
551/// 语言
552#[derive(Clone, Debug)]
553pub enum Language {
554    ZhCN,
555    ZhHans,
556    En,
557    Other(String),
558
559}
560impl Language {
561    #[must_use]
562    pub fn from(name: &str) -> Self {
563        let binding = name.split(',').collect::<Vec<&str>>()[0].trim().to_lowercase();
564        let name = binding.as_str();
565        match name {
566            "zh-cn" => Self::ZhCN,
567            "zh-hans" => Self::ZhHans,
568            "en" => Self::En,
569            _ => Self::Other(name.to_string()),
570        }
571    }
572    #[must_use]
573    pub fn str(&self) -> &str {
574        match self {
575            Language::ZhCN => "zh-CN",
576            Language::ZhHans => "zh-Hans",
577            Language::En => "en",
578            Language::Other(e) => e.as_str(),
579        }
580    }
581}
582
583
584/// 压缩方式
585#[derive(Clone, Debug)]
586pub enum Encoding {
587    Gzip,
588    Deflate,
589    Br,
590    Bzip2,
591    None,
592}
593impl Encoding {
594    #[must_use]
595    pub fn from(s: &str) -> Encoding {
596        match s.to_lowercase().as_str() {
597            x if x.contains("gzip") => Encoding::Gzip,
598            x if x.contains("deflate") => Encoding::Deflate,
599            x if x.contains("br") => Encoding::Br,
600            x if x.contains("bzip2") => Encoding::Bzip2,
601            _ => Encoding::None,
602        }
603    }
604    #[must_use]
605    pub fn str(&self) -> &str {
606        match self {
607            Encoding::Gzip => "gzip",
608            Encoding::Deflate => "deflate",
609            Encoding::Br => "br",
610            Encoding::None => "",
611            Encoding::Bzip2 => "bzip2",
612        }
613    }
614    pub fn compress(self, data: &[u8]) -> io::Result<Vec<u8>> {
615        match self {
616            Encoding::Gzip => {
617                let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
618                encoder.write_all(data)?;
619                encoder.finish()
620            }
621            _ => Ok(data.to_vec()),
622        }
623    }
624}