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#[derive(Clone, Debug)]
29pub struct WebServer;
30
31impl WebServer {
32 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 stream.set_read_timeout(Some(Duration::from_secs(30))).unwrap_or_default();
74 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 return Err(Error::other(e.body.as_str()));
95 }
96 };
97 match response.handle() {
98 Ok(()) => {}
99 Err(e) => {
100 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 stream.set_read_timeout(Some(Duration::from_secs(15))).unwrap_or_default();
117 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
183impl<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
193impl 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 fn on_request(&mut self, _request: Request, _response: &mut Response);
202 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 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 if !response.headers.has_key("Access-Control-Allow-Credentials") {
217 response.header("Access-Control-Allow-Credentials", "true");
218 }
219 }
224
225 fn on_frame(&mut self) -> Result<(), HttpError> {
226 Ok(())
227 }
228 fn on_open(&mut self) -> Result<(), HttpError> {
230 Ok(())
231 }
232 fn on_message(&mut self, _msg: Message) -> Result<(), HttpError> {
234 Ok(())
235 }
236 fn on_close(&mut self, _code: CloseCode, _reason: &str) {}
238 fn on_error(&mut self, _err: ErrorCode) {}
240 fn on_shutdown(&mut self) {}
242}
243
244
245#[derive(Clone, Debug)]
246pub enum Connection {
247 KeepAlive,
249 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#[derive(Clone, Debug)]
297#[derive(Default)]
298pub struct Uri {
299 pub uri: String,
301 pub url: String,
303 pub query: String,
305 pub fragment: String,
307 pub path: String,
309 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 #[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#[derive(Clone, Debug)]
364pub enum Method {
365 POST,
367 GET,
369 HEAD,
371 PUT,
373 DELETE,
375 OPTIONS,
377 PATCH,
378 TRACE,
379 VIEW,
380 CONNECT,
381 PROPFIND,
382 PRI,
384 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 #[must_use]
435 pub fn new(code: u16, body: &str) -> Self {
436 Self {
437 code,
438 body: body.to_string(),
439 }
440 }
441}
442#[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#[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#[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#[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#[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}