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