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
481pub(crate) fn parse_content_type_header_value(
490 value: &str,
491) -> (String, std::collections::HashMap<String, String>) {
492 let mut it = value.split(';');
493 let mime = it.next().unwrap_or("").trim().to_lowercase();
494
495 let mut params = std::collections::HashMap::<String, String>::new();
496 for raw in it {
497 let raw = raw.trim();
498 if raw.is_empty() {
499 continue;
500 }
501 if let Some((k, v)) = raw.split_once('=') {
502 let key = k.trim().to_lowercase();
503 let mut val = v.trim();
504 if val.len() >= 2 && val.starts_with('"') && val.ends_with('"') {
505 val = &val[1..val.len() - 1];
506 }
507 params.insert(key, val.to_string());
508 } else {
509 params.insert(raw.to_lowercase(), String::new());
511 }
512 }
513
514 (mime, params)
515}
516#[derive(Clone, Debug)]
518pub enum Authorization {
519 Basic(String, String),
520 Bearer(String),
521 Digest(JsonValue),
522 Other(String),
523}
524impl Authorization {
525 #[must_use]
526 pub fn from(data: &str) -> Self {
527 let authorization = data.split_whitespace().collect::<Vec<&str>>();
528 let mode = authorization[0].to_lowercase();
529 match mode.as_str() {
530 "basic" => {
531 let text = br_crypto::base64::decode(&authorization[1].to_string().clone());
532 let text: Vec<&str> = text.split(':').collect();
533 Self::Basic(text[0].to_string(), text[1].to_string())
534 }
535 "bearer" => Self::Bearer(authorization[1].to_string()),
536 "digest" => {
537 let text = authorization[1..].concat().clone();
538 let text = text.split(',').collect::<Vec<&str>>();
539 let mut params = object! {};
540 for item in &text {
541 let Some(index) = item.find('=') else { continue };
542 let key = item[..index].to_string();
543 let value = item[index + 2..item.len() - 1].to_string();
544 let _ = params.insert(key.as_str(), value);
545 }
546 Self::Digest(params)
547 }
548 _ => Self::Other(data.to_string())
549 }
550 }
551 pub fn str(&mut self) -> JsonValue {
552 match self {
553 Authorization::Basic(key, value) => {
554 let mut data = object! {};
555 data[key.as_str()] = value.clone().into();
556 data
557 }
558 Authorization::Bearer(e) => e.clone().into(),
559 Authorization::Digest(e) => e.clone(),
560 Authorization::Other(name) => name.clone().into(),
561 }
562 }
563}
564#[derive(Clone, Debug)]
566pub enum Content {
567 FormUrlencoded(JsonValue),
568 FormData(JsonValue),
569 Json(JsonValue),
570 Text(JsonValue),
571 Xml(JsonValue),
572 None,
573}
574impl Content {}
575#[derive(Clone, Debug)]
576pub enum FormData {
577 File(String, PathBuf),
578 Field(JsonValue),
579}
580
581#[derive(Clone, Debug)]
583pub enum Language {
584 ZhCN,
585 ZhHans,
586 En,
587 Other(String),
588
589}
590impl Language {
591 #[must_use]
592 pub fn from(name: &str) -> Self {
593 let binding = name.split(',').collect::<Vec<&str>>()[0].trim().to_lowercase();
594 let name = binding.as_str();
595 match name {
596 "zh-cn" => Self::ZhCN,
597 "zh-hans" => Self::ZhHans,
598 "en" => Self::En,
599 _ => Self::Other(name.to_string()),
600 }
601 }
602 #[must_use]
603 pub fn str(&self) -> &str {
604 match self {
605 Language::ZhCN => "zh-CN",
606 Language::ZhHans => "zh-Hans",
607 Language::En => "en",
608 Language::Other(e) => e.as_str(),
609 }
610 }
611}
612
613
614#[derive(Clone, Debug)]
616pub enum Encoding {
617 Gzip,
618 Deflate,
619 Br,
620 Bzip2,
621 None,
622}
623impl Encoding {
624 #[must_use]
625 pub fn from(s: &str) -> Encoding {
626 match s.to_lowercase().as_str() {
627 x if x.contains("gzip") => Encoding::Gzip,
628 x if x.contains("deflate") => Encoding::Deflate,
629 x if x.contains("br") => Encoding::Br,
630 x if x.contains("bzip2") => Encoding::Bzip2,
631 _ => Encoding::None,
632 }
633 }
634 #[must_use]
635 pub fn str(&self) -> &str {
636 match self {
637 Encoding::Gzip => "gzip",
638 Encoding::Deflate => "deflate",
639 Encoding::Br => "br",
640 Encoding::Bzip2 => "bzip2",
641 Encoding::None => "",
642 }
643 }
644 pub fn compress(&mut self, data: &[u8]) -> Result<Vec<u8>, String> {
646 match self {
647 Encoding::Gzip => {
648 let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
649 match encoder.write_all(data) {
650 Ok(()) => {}
651 Err(e) => {
652 return Err(format!("Failed to compress file {}", e));
653 }
654 };
655 match encoder.finish() {
656 Ok(e) => Ok(e),
657 Err(e) => Err(format!("Failed to compress file {}", e))
658 }
659 }
660 _ => Ok(data.to_vec()),
661 }
662 }
663 pub fn decompress(&mut self, data: &[u8]) -> Result<Vec<u8>, String> {
665 match self {
666 Encoding::Gzip => {
667 let mut d = GzDecoder::new(data);
668 let mut s = String::new();
669 match d.read_to_string(&mut s) {
670 Ok(_) => {}
671 Err(e) => {
672 return Err(format!("Failed to decompress file {}", e));
673 }
674 };
675 Ok(s.as_bytes().to_vec())
676 }
677 Encoding::Br => {
678 let mut decompressed = Vec::new();
679 let mut reader = brotli::Decompressor::new(data, 4096);
680 reader.read_to_end(&mut decompressed).map_err(|e| format!("brotli decompress error: {e}"))?;
681 Ok(decompressed)
682 }
683 _ => Ok(data.to_vec()),
684 }
685 }
686}
687
688#[derive(Clone, Debug)]
690pub enum Protocol {
691 HTTP1_0,
692 HTTP1_1,
693 HTTP2,
694 HTTP3,
695 Other(String),
696}
697
698impl Protocol {
699 pub fn from(name: &str) -> Self {
700 match name.to_lowercase().as_str() {
701 "http/1.0" => Protocol::HTTP1_0,
702 "http/1.1" => Protocol::HTTP1_1,
703 "http/2.0" | "http/2" => Protocol::HTTP2,
704 "http/3.0" | "http/3" => Protocol::HTTP3,
705 _ => Protocol::Other(name.to_lowercase())
706 }
707 }
708 pub fn str(&self) -> &str {
709 match self {
710 Protocol::HTTP1_0 => "HTTP/1.0",
711 Protocol::HTTP1_1 => "HTTP/1.1",
712 Protocol::HTTP2 => "HTTP/2.0",
713 Protocol::HTTP3 => "HTTP/3.0",
714 Protocol::Other(protocol) => protocol.as_str(),
715 }
716 }
717}
718#[derive(Clone, Debug)]
720pub struct Status {
721 pub code: u16,
722 reason: String,
723}
724impl Status {
725 pub fn set_code(&mut self, code: u16) {
726 self.code = code;
727 self.reason = match code {
728 100 => "Continue", 101 => "Switching Protocols", 102 => "Processing",
731 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",
747 404 => "Not Found", 405 => "Method Not Allowed", 411 => "Length Required", 413 => "Payload Too Large", 414 => "URI Too Long", 416 => "Range Not Satisfiable",
753 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", _ => "",
763 }.to_string();
764 }
765 pub fn from(code: u16, reason: &str) -> Self {
766 Status {
767 code,
768 reason: reason.to_string(),
769 }
770 }
771}
772impl Default for Status {
773 fn default() -> Self {
774 Self {
775 code: 200,
776 reason: "OK".to_string(),
777 }
778 }
779}
780
781#[derive(Debug)]
782pub enum TransferEncoding {
783 Chunked,
784 Other(String),
785}
786impl TransferEncoding {
787 pub fn from(name: &str) -> TransferEncoding {
788 match name.to_lowercase().as_str() {
789 "chunked" => TransferEncoding::Chunked,
790 _ => TransferEncoding::Other(name.to_string()),
791 }
792 }
793}
794
795pub fn split_boundary(mut data: Vec<u8>, boundary: &str) -> Result<Vec<Vec<u8>>, String> {
796 let boundary = format!("--{boundary}");
797 let mut list = vec![];
798 loop {
799 if let Some(n) = data.to_vec().windows(boundary.len()).position(|x| x == boundary.as_bytes()) {
800 data.drain(n..boundary.len());
801 if data.is_empty() || data == "--\r\n".as_bytes().to_vec() {
802 break;
803 }
804 } else {
805 return Err("格式错误1".to_string());
806 }
807 if let Some(n) = data.to_vec().windows(boundary.len()).position(|x| x == boundary.as_bytes()) {
808 list.push(data[..n].to_vec());
809 data.drain(..n);
810 } else {
811 return Err("格式错误2".to_string());
812 }
813 }
814 Ok(list)
815}