1mod stream;
2pub mod config;
3pub mod request;
4pub mod response;
5pub mod websocket;
6#[cfg(feature = "client")]
7pub mod client;
8mod url;
9mod client_response;
10
11use fs::read;
12use crate::stream::{Scheme};
13use crate::config::{Config};
14use crate::request::{Request};
15use crate::response::Response;
16use crate::websocket::{CloseCode, ErrorCode, Message, Websocket};
17use log::{error, info, warn};
18
19use rustls_pemfile::{certs};
20
21use std::io::{BufReader, Error, Read, Write};
22use std::net::{TcpListener};
23use std::sync::{Arc, Mutex};
24use std::time::{Duration};
25use std::{fs, io, thread};
26use std::fmt::Debug;
27use std::path::{PathBuf};
28use flate2::Compression;
29use flate2::read::GzDecoder;
30use flate2::write::GzEncoder;
31use json::{object, JsonValue};
32use rustls::{ServerConfig, ServerConnection, StreamOwned};
33
34#[derive(Clone, Debug)]
36pub struct WebServer;
37
38impl WebServer {
39 pub fn new_service(config: Config, factory: fn(out: Websocket) -> Box<dyn Handler>) {
41 loop {
42 match WebServer::service(config.clone(), factory) {
43 Ok(()) => {}
44 Err(e) => error!("服务器错误: {}[{}]: {}", file!(), line!(), e),
45 }
46 warn!("服务器 1秒后重启");
47 thread::sleep(Duration::from_secs(1));
48 }
49 }
50 fn service(config: Config, factory: fn(out: Websocket) -> Box<dyn Handler>) -> io::Result<()> {
51 info!("==================== 网络服务 服务信息 ====================");
52 info!("日志记录: {}",if config.log {"开启"} else {"关闭"});
53 info!("调试模式: {}",if config.debug { "开启" } else { "关闭" });
54 info!("监听地址: {}", config.host);
55 info!("服务地址: {}://{}",if config.https { "https" } else { "http" },config.host);
56 info!("根 目 录: {}", config.root_path.to_str().unwrap());
57 info!("访问目录: {}", config.public);
58 info!("运行目录: {}", config.runtime);
59 info!("SSL/TLS: {}",if config.https { "开启" } else { "关闭" });
60
61 if config.https {
62 info!("证书目录KEY: {:?}", config.tls.key);
63 info!("证书目录PEM: {:?}", config.tls.certs);
64 }
65
66 let listener = TcpListener::bind(config.host.clone())?;
67 info!("==================== 网络服务 启动成功 ====================");
68
69 let acceptor = Self::ssl(config.clone())?;
70 for stream in listener.incoming() {
71 match stream {
72 Ok(stream) => {
73 let config_new = config.clone();
74 let acceptor_new = acceptor.clone();
75 thread::spawn(move || -> io::Result<()> {
76 stream.set_nonblocking(false)?;
77 stream.set_read_timeout(Some(Duration::from_secs(30))).unwrap_or_default();
79 stream.set_write_timeout(Some(Duration::from_secs(30))).unwrap_or_default();
81
82 let scheme = if config_new.https {
83 let conn = match ServerConnection::new(acceptor_new.unwrap()) {
84 Ok(e) => e,
85 Err(e) => {
86 return Err(Error::other(e.to_string()));
87 }
88 };
89 Scheme::Https(Arc::new(Mutex::new(StreamOwned::new(conn, stream))))
90 } else {
91 Scheme::Http(Arc::new(Mutex::new(stream)))
92 };
93
94
95 let mut request = Request::new(config_new.clone(), Arc::new(Mutex::new(scheme.clone())));
96 let response = match request.handle() {
97 Ok(()) => Response::new(&request.clone(), factory),
98 Err(e) => {
99 return Err(Error::other(e.body.as_str()));
101 }
102 };
103 match response.handle() {
104 Ok(()) => {}
105 Err(e) => {
106 return Err(Error::other(e));
108 }
109 };
110
111 match request.save_log() {
112 Ok(()) => {}
113 Err(_) => error!("日志记录错误")
114 }
115 Ok(())
116 });
117 }
118 Err(e) => return Err(e),
119 }
120 }
121 Ok(())
122 }
123 fn ssl(config: Config) -> io::Result<Option<Arc<ServerConfig>>> {
124 if config.https {
125 if !config.tls.key.is_file() {
126 return Err(Error::other(
127 format!("private.key 不存在: {:?}", config.tls.key.clone()).as_str(),
128 ));
129 }
130 if !config.tls.certs.is_file() {
131 return Err(Error::other(
132 format!("certificate.pem 不存在: {:?}", config.tls.certs).as_str(),
133 ));
134 }
135 let t = read(config.tls.key)?;
136 let mut reader = BufReader::new(t.as_slice());
137 let key = rustls_pemfile::private_key(&mut reader).unwrap().unwrap();
138 let t = read(config.tls.certs)?;
139 let mut reader = BufReader::new(t.as_slice());
140 let certs = certs(&mut reader).collect::<Result<Vec<_>, _>>()?.as_slice().to_owned();
141
142 let config = match ServerConfig::builder()
143 .with_no_client_auth()
145 .with_single_cert(certs, key) {
147 Ok(e) => e,
148 Err(e) => {
149 return Err(Error::other(e))
150 }
151 };
152
153 Ok(Some(Arc::new(config)))
154 } else {
169 Ok(None)
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 }
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 H2c,
269 Other(String),
270}
271impl Upgrade {
272 fn from(name: &str) -> Self {
273 match name.to_lowercase().as_str() {
274 "websocket" => Upgrade::Websocket,
275 "http" => Upgrade::Http,
276 "h2c" => Upgrade::H2c,
277 _ => Upgrade::Other(name.to_lowercase().as_str().to_string()),
278 }
279 }
280 pub fn str(&self) -> &str {
281 match self {
282 Upgrade::Websocket => "websocket",
283 Upgrade::Http => "http",
284 Upgrade::H2c => "h2c",
285 Upgrade::Other(name) => name,
286 }
287 }
288}
289
290#[derive(Clone, Debug)]
292#[derive(Default)]
293pub struct Uri {
294 pub uri: String,
296 pub url: String,
298 pub query: String,
300 pub fragment: String,
302 pub path: String,
304 pub path_segments: Vec<String>,
306}
307impl Uri {
308 pub fn from(url: &str) -> Self {
309 let mut decoded_url = br_crypto::encoding::urlencoding_decode(url);
310 let fragment = match decoded_url.rfind('#') {
311 None => String::new(),
312 Some(index) => decoded_url.drain(index..).collect::<String>(),
313 };
314
315 let query = match decoded_url.rfind('?') {
316 None => String::new(),
317 Some(index) => decoded_url.drain(index..).collect::<String>().trim_start_matches("?").to_string(),
318 };
319
320 let path_segments = decoded_url.split('/').map(|x| x.to_string()).filter(|x| !x.is_empty()).collect::<Vec<String>>();
321 Self {
322 uri: decoded_url.clone(),
323 url: url.to_string(),
324 query,
325 fragment,
326 path: decoded_url.clone(),
327 path_segments,
328 }
329 }
330 #[must_use]
332 pub fn get_query_params(&self) -> JsonValue {
333 let text = self.query.split('&').collect::<Vec<&str>>();
334 let mut params = object! {};
335 for item in text {
336 if let Some(index) = item.find('=') {
337 let key = item[..index].to_string();
338 let value = item[index + 1..].to_string();
339 let _ = params.insert(key.as_str(), value);
340 }
341 }
342 params
343 }
344 #[must_use]
345 pub fn to_json(&self) -> JsonValue {
346 object! {
347 url: self.url.clone(),
348 query: self.query.clone(),
349 fragment: self.fragment.clone(),
350 path: self.path.clone(),
351 path_segments: self.path_segments.clone()
352 }
353 }
354}
355
356
357#[derive(Clone, Debug)]
359pub enum Method {
360 POST,
362 GET,
364 HEAD,
366 PUT,
368 DELETE,
370 OPTIONS,
372 PATCH,
373 TRACE,
374 VIEW,
375 CONNECT,
376 PROPFIND,
377 PRI,
379 Other(String),
381}
382
383impl Method {
384 #[must_use]
385 pub fn from(name: &str) -> Self {
386 match name.to_lowercase().as_str() {
387 "post" => Self::POST,
388 "get" => Self::GET,
389 "head" => Self::HEAD,
390 "put" => Self::PUT,
391 "delete" => Self::DELETE,
392 "options" => Self::OPTIONS,
393 "patch" => Self::PATCH,
394 "trace" => Self::TRACE,
395 "view" => Self::VIEW,
396 "propfind" => Self::PROPFIND,
397 "connect" => Self::CONNECT,
398 "pri" => Self::PRI,
399 _ => Self::Other(name.to_string()),
400 }
401 }
402 pub fn str(&mut self) -> &str {
403 match self {
404 Method::POST => "POST",
405 Method::GET => "GET",
406 Method::HEAD => "HEAD",
407 Method::PUT => "PUT",
408 Method::DELETE => "DELETE",
409 Method::OPTIONS => "OPTIONS",
410 Method::PATCH => "PATCH",
411 Method::TRACE => "TRACE",
412 Method::VIEW => "VIEW",
413 Method::PROPFIND => "PROPFIND",
414 Method::PRI => "PRI",
415 Method::CONNECT => "CONNECT",
416 Method::Other(e) => e.to_lowercase().leak()
417 }
418 }
419}
420
421#[derive(Debug, Clone)]
422pub struct HttpError {
423 pub code: u16,
424 pub body: String,
425}
426
427impl HttpError {
428 #[must_use]
430 pub fn new(code: u16, body: &str) -> Self {
431 Self {
432 code,
433 body: body.to_string(),
434 }
435 }
436}
437#[derive(Debug, Clone)]
439pub enum ContentType {
440 FormData,
441 FormUrlencoded,
442 Json,
443 Xml,
444 Javascript,
445 Text,
446 Html,
447 Stream,
448 Other(String),
449}
450impl ContentType {
451 #[must_use]
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 #[must_use]
466 pub fn str(&self) -> &str {
467 match self {
468 ContentType::FormData => "multipart/form-data",
469 ContentType::FormUrlencoded => "application/x-www-form-urlencoded",
470 ContentType::Json => "application/json",
471 ContentType::Xml => "application/xml",
472 ContentType::Javascript => "application/javascript",
473 ContentType::Text => "text/plain",
474 ContentType::Html => "text/html",
475 ContentType::Other(name) => name.as_str(),
476 ContentType::Stream => "application/octet-stream"
477 }
478 }
479}
480#[derive(Clone, Debug)]
482pub enum Authorization {
483 Basic(String, String),
484 Bearer(String),
485 Digest(JsonValue),
486 Other(String),
487}
488impl Authorization {
489 #[must_use]
490 pub fn from(data: &str) -> Self {
491 let authorization = data.split_whitespace().collect::<Vec<&str>>();
492 let mode = authorization[0].to_lowercase();
493 match mode.as_str() {
494 "basic" => {
495 let text = br_crypto::base64::decode(&authorization[1].to_string().clone());
496 let text: Vec<&str> = text.split(':').collect();
497 Self::Basic(text[0].to_string(), text[1].to_string())
498 }
499 "bearer" => Self::Bearer(authorization[1].to_string()),
500 "digest" => {
501 let text = authorization[1..].concat().clone();
502 let text = text.split(',').collect::<Vec<&str>>();
503 let mut params = object! {};
504 for item in &text {
505 let Some(index) = item.find('=') else { continue };
506 let key = item[..index].to_string();
507 let value = item[index + 2..item.len() - 1].to_string();
508 let _ = params.insert(key.as_str(), value);
509 }
510 Self::Digest(params)
511 }
512 _ => Self::Other(data.to_string())
513 }
514 }
515 pub fn str(&mut self) -> JsonValue {
516 match self {
517 Authorization::Basic(key, value) => {
518 let mut data = object! {};
519 data[key.as_str()] = value.clone().into();
520 data
521 }
522 Authorization::Bearer(e) => e.clone().into(),
523 Authorization::Digest(e) => e.clone(),
524 Authorization::Other(name) => name.clone().into(),
525 }
526 }
527}
528#[derive(Clone, Debug)]
530pub enum Content {
531 FormUrlencoded(JsonValue),
532 FormData(JsonValue),
533 Json(JsonValue),
534 Text(JsonValue),
535 Xml(JsonValue),
536 None,
537}
538impl Content {}
539#[derive(Clone, Debug)]
540pub enum FormData {
541 File(String, PathBuf),
542 Field(JsonValue),
543}
544
545#[derive(Clone, Debug)]
547pub enum Language {
548 ZhCN,
549 ZhHans,
550 En,
551 Other(String),
552
553}
554impl Language {
555 #[must_use]
556 pub fn from(name: &str) -> Self {
557 let binding = name.split(',').collect::<Vec<&str>>()[0].trim().to_lowercase();
558 let name = binding.as_str();
559 match name {
560 "zh-cn" => Self::ZhCN,
561 "zh-hans" => Self::ZhHans,
562 "en" => Self::En,
563 _ => Self::Other(name.to_string()),
564 }
565 }
566 #[must_use]
567 pub fn str(&self) -> &str {
568 match self {
569 Language::ZhCN => "zh-CN",
570 Language::ZhHans => "zh-Hans",
571 Language::En => "en",
572 Language::Other(e) => e.as_str(),
573 }
574 }
575}
576
577
578#[derive(Clone, Debug)]
580pub enum Encoding {
581 Gzip,
582 Deflate,
583 Br,
584 Bzip2,
585 None,
586}
587impl Encoding {
588 #[must_use]
589 pub fn from(s: &str) -> Encoding {
590 match s.to_lowercase().as_str() {
591 x if x.contains("gzip") => Encoding::Gzip,
592 x if x.contains("deflate") => Encoding::Deflate,
593 x if x.contains("br") => Encoding::Br,
594 x if x.contains("bzip2") => Encoding::Bzip2,
595 _ => Encoding::None,
596 }
597 }
598 #[must_use]
599 pub fn str(&self) -> &str {
600 match self {
601 Encoding::Gzip => "gzip",
602 Encoding::Deflate => "deflate",
603 Encoding::Br => "br",
604 Encoding::Bzip2 => "bzip2",
605 Encoding::None => "",
606 }
607 }
608 pub fn compress(&mut self, data: &[u8]) -> Result<Vec<u8>, String> {
610 match self {
611 Encoding::Gzip => {
612 let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
613 match encoder.write_all(data) {
614 Ok(()) => {}
615 Err(e) => {
616 return Err(format!("Failed to compress file {}", e));
617 }
618 };
619 match encoder.finish() {
620 Ok(e) => Ok(e),
621 Err(e) => Err(format!("Failed to compress file {}", e))
622 }
623 }
624 _ => Ok(data.to_vec()),
625 }
626 }
627 pub fn decompress(&mut self, data: &[u8]) -> Result<Vec<u8>, String> {
629 match self {
630 Encoding::Gzip => {
631 let mut d = GzDecoder::new(data);
632 let mut s = String::new();
633 match d.read_to_string(&mut s) {
634 Ok(_) => {}
635 Err(e) => {
636 return Err(format!("Failed to decompress file {}", e));
637 }
638 };
639 Ok(s.as_bytes().to_vec())
640 }
641 _ => Ok(data.to_vec()),
642 }
643 }
644}
645
646#[derive(Clone, Debug)]
648pub enum Protocol {
649 HTTP1_0,
650 HTTP1_1,
651 HTTP2,
652 HTTP3,
653 Other(String),
654}
655
656impl Protocol {
657 pub fn from(name: &str) -> Self {
658 match name.to_lowercase().as_str() {
659 "http/1.0" => Protocol::HTTP1_0,
660 "http/1.1" => Protocol::HTTP1_1,
661 "http/2.0" | "http/2" => Protocol::HTTP2,
662 "http/3.0" | "http/3" => Protocol::HTTP3,
663 _ => Protocol::Other(name.to_lowercase())
664 }
665 }
666 pub fn str(&self) -> &str {
667 match self {
668 Protocol::HTTP1_0 => "HTTP/1.0",
669 Protocol::HTTP1_1 => "HTTP/1.1",
670 Protocol::HTTP2 => "HTTP/2.0",
671 Protocol::HTTP3 => "HTTP/3.0",
672 Protocol::Other(protocol) => protocol.as_str(),
673 }
674 }
675}
676#[derive(Clone, Debug)]
678pub struct Status {
679 pub code: u16,
680 reason: String,
681}
682impl Status {
683 pub fn set_code(&mut self, code: u16) {
684 self.code = code;
685 self.reason = match code {
686 100 => "Continue", 101 => "Switching Protocols", 102 => "Processing",
689 103 => "Early Hints", 200 => "OK", 201 => "Created", 202 => "Accepted", 204 => "No Content", 206 => "Partial Content", 301 => "Moved Permanently", 302 => "Found", 303 => "See Other", 304 => "Not Modified", 307 => "Temporary Redirect", 308 => "Permanent Redirect", 400 => "Bad Request", 401 => "Unauthorized", 403 => "Forbidden",
705 404 => "Not Found", 405 => "Method Not Allowed", 411 => "Length Required", 413 => "Payload Too Large", 414 => "URI Too Long", 416 => "Range Not Satisfiable",
711 429 => "Too Many Requests", 431 => "Request Header Fields Too Large", 500 => "Internal Server Error", 501 => "Not Implemented", 502 => "Bad Gateway", 503 => "Service Unavailable", 504 => "Gateway Time-out", 505 => "HTTP Version Not Supported", _ => "",
721 }.to_string();
722 }
723 pub fn from(code: u16, reason: &str) -> Self {
724 Status {
725 code,
726 reason: reason.to_string(),
727 }
728 }
729}
730impl Default for Status {
731 fn default() -> Self {
732 Self {
733 code: 200,
734 reason: "OK".to_string(),
735 }
736 }
737}
738
739#[derive(Debug)]
740pub enum TransferEncoding {
741 Chunked,
742 Other(String),
743}
744impl TransferEncoding {
745 pub fn from(name: &str) -> TransferEncoding {
746 match name.to_lowercase().as_str() {
747 "chunked" => TransferEncoding::Chunked,
748 _ => TransferEncoding::Other(name.to_string()),
749 }
750 }
751}
752
753pub fn split_boundary(mut data: Vec<u8>, boundary: &str) -> Result<Vec<Vec<u8>>, String> {
754 let boundary = format!("--{boundary}");
755 let mut list = vec![];
756 loop {
757 if let Some(n) = data.to_vec().windows(boundary.len()).position(|x| x == boundary.as_bytes()) {
758 data.drain(n..boundary.len());
759 if data.is_empty() || data == "--\r\n".as_bytes().to_vec() {
760 break;
761 }
762 } else {
763 return Err("格式错误1".to_string());
764 }
765 if let Some(n) = data.to_vec().windows(boundary.len()).position(|x| x == boundary.as_bytes()) {
766 list.push(data[..n].to_vec());
767 data.drain(..n);
768 } else {
769 return Err("格式错误2".to_string());
770 }
771 }
772 Ok(list)
773}