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