1use async_trait::async_trait;
2use fnv::FnvHashMap;
3use tokio::sync::Mutex;
4use urlpattern::UrlPatternMatchInput;
5use core::fmt;
6use std::{
7 io,
8 net::{SocketAddr, ToSocketAddrs},
9 path::PathBuf, pin::Pin, sync::Arc, any::{Any, TypeId}, ops::Deref, fmt::Formatter,
10};
11
12use hyper::Body;
13
14use crate::{server::{util::{get_certs_and_key, process_result}, http_server::{launch_http_server, HttpServerOpt}, https_server::{launch_https_server, HttpsServerOpt}, http3_server::{launch_http3_server, Http3ServerOpt}}, process::save_pid, resource::{Resource, Responder}};
15
16
17#[derive(Default)]
18pub struct Data (FnvHashMap<TypeId, Box<dyn Any + Sync + Send>>);
19
20impl Deref for Data {
21 type Target = FnvHashMap<TypeId, Box<dyn Any + Sync + Send>>;
22
23 fn deref(&self) -> &Self::Target {
24 &self.0
25 }
26}
27
28impl Data {
29 pub fn new(data: FnvHashMap<TypeId, Box<dyn Any + Sync + Send>>) -> Self {
30 Self(data)
31 }
32
33 pub fn default() -> Self {
34 Self(FnvHashMap::default())
35 }
36
37 pub fn insert<D>(&mut self, data: D)
38 where
39 D: Any + Send + Sync,
40 {
41 self.0.insert(TypeId::of::<D>(), Box::new(data));
42 }
43}
44
45impl fmt::Debug for Data {
46 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
47 f.debug_tuple("Data").finish()
48 }
49}
50
51pub type Result<T, E = ChiteyError> = std::result::Result<T, E>;
52
53pub struct ContextImpl {
54 pub(crate) data: Data,
55}
56
57impl ContextImpl {
58 pub fn new() -> Self {
59 ContextImpl { data: Data::new(FnvHashMap::default()) }
60 }
61
62 #[must_use]
63 pub fn insert<D>(mut self, data: D) -> Self
64 where
65 D: Any + Send + Sync,
66 {
67 self.data.insert(data);
68 self
69 }
70}
71
72#[derive(Clone)]
73pub struct Context {
74 data: Arc<ContextImpl>,
75}
76
77impl Context {
78 pub fn new(data: ContextImpl) -> Self {
79 Self {
80 data: Arc::new(data),
81 }
82 }
83
84 pub fn get<D>(&self) -> &D
85 where
86 D: Any + Send + Sync,
87 {
88 self.data_opt::<D>().unwrap_or_else(|| panic!("Data `{}` does not exist.", std::any::type_name::<D>()))
89 }
90
91 pub fn data_opt<D>(&self) -> Option<&D>
92 where
93 D: Any + Send + Sync,
94 {
95 self.data.data.get(&TypeId::of::<D>()).and_then(|d| d.downcast_ref::<D>())
96 }
97}
98
99#[derive(Clone)]
100pub struct Factories {
101 pub(crate) factories: Vec<(Arc<Resource>, Arc<Mutex<Pin<Box<dyn HttpServiceFactory + 'static + Send + Sync>>>>)>,
102 pub(crate) contexts: Context,
103}
104unsafe impl Send for Factories {}
105unsafe impl Sync for Factories {}
106
107#[derive(Clone)]
108pub struct Certs {
109 pub cert: PathBuf,
110 pub key: PathBuf,
111}
112
113#[async_trait]
114pub trait HttpServiceFactory: Sync
115{
116 fn register(&self) -> Resource;
117 fn analyze_types(&self, url: UrlPatternMatchInput) -> bool;
118 async fn handler_func(&self, url: UrlPatternMatchInput, req: Request) -> Responder;
119}
120
121pub struct WebServer {
122 cert: Option<Certs>,
123 listen: Option<SocketAddr>,
124 tls_listen: Option<SocketAddr>,
125 redirect: Option<String>,
126 factories: Vec<(Resource, Pin<Box<dyn HttpServiceFactory + 'static + Send + Sync>>)>,
127 data: Data,
128}
129
130impl WebServer
131{
132 pub fn new() -> Self {
133 Self {
134 cert: None,
135 listen: None,
136 tls_listen: None,
137 redirect: None,
138 factories: Vec::new(),
139 data: Data::default(),
140 }
141 }
142
143 pub fn service<F>(mut self, factory: F) -> Self
144 where
145 F: HttpServiceFactory + 'static + Send + Sync,
146 {
147 let resource = factory.register();
148 self.factories.push((resource, Box::pin(factory)));
149 self
150 }
151
152 pub fn bind<A>(mut self, address: A) -> io::Result<Self>
153 where
154 A: ToSocketAddrs,
155 {
156 match address.to_socket_addrs() {
157 Ok(v) => {
158 for addr in v.collect::<Vec<SocketAddr>>() {
159 self.listen = Some(addr);
160 }
161 }
162 Err(e) => return Err(e),
163 };
164
165 Ok(self)
166 }
167
168 pub fn tls_bind<A>(mut self, address: A) -> io::Result<Self>
169 where
170 A: ToSocketAddrs,
171 {
172 match address.to_socket_addrs() {
173 Ok(v) => {
174 for addr in v.collect::<Vec<SocketAddr>>() {
175 self.tls_listen = Some(addr);
176 }
177 }
178 Err(e) => return Err(e),
179 };
180
181 Ok(self)
182 }
183
184 pub fn redirect<U: std::ops::Deref<Target=str>>(mut self, url: U) -> Self {
185 self.redirect = Some(url.to_string());
186 self
187 }
188
189 pub fn tls(mut self, cert: Certs) -> Self {
190 self.cert = Some(cert);
191 self
192 }
193
194 pub async fn run(self) -> Result<(), ChiteyError> {
195 let mut factories = Vec::new();
196 let mut factories2 = Vec::new();
197 for factory in self.factories {
198 let (res, fact) = factory;
199 let fac = Arc::new(Mutex::new(fact));
200 factories.push((Arc::new(res.clone()), fac.clone()));
201 factories2.push((Arc::new(res), fac.clone()));
202 }
203
204 let contexts = Context::new(ContextImpl { data: self.data });
205 let factories = Factories{ factories, contexts: contexts.clone() };
206 let factories2 = Factories{ factories: factories2, contexts: contexts.clone() };
207
208 if let Some(cert) = self.cert {
209 let tls_certs_key = match get_certs_and_key(cert) {
210 Ok(v) => v,
211 Err(e) => return Err(ChiteyError::KeyAnalyzeError(e.to_string())),
212 };
213 let tls_certs_key2 = tls_certs_key.clone();
214 let handle_http = async {
215 let factories = factories.clone();
216 if let Some(li) = self.listen {
217 let http_server_opt = HttpServerOpt{ listen: li, redirect: self.redirect };
218 let _ = tokio::spawn(async move {
219 loop {
220 process_result(launch_http_server(http_server_opt.clone(), save_pid, factories.clone()).await);
221 };
222 }).await;
223 }
224 };
225 let factories = factories.clone();
226 let handle_https = async {
227 if let Some(li) = self.tls_listen {
228 let https_server_opt = HttpsServerOpt{listen: li};
229 let http3_server_opt = Http3ServerOpt{listen: li};
230 let handle_https = tokio::spawn(async move {
231 loop {
232 process_result(launch_https_server(tls_certs_key.clone(), https_server_opt.clone(), factories.clone()).await);
233 }
234 });
235 let handle_http3 = tokio::spawn(async move {
236 loop {
237 process_result(launch_http3_server(tls_certs_key2.clone(), http3_server_opt.clone(), factories2.clone()).await);
238 }
239 });
240 let (_, _) = tokio::join!(handle_https, handle_http3);
241 }
242 };
243
244 let (_, _) = tokio::join!(
245 handle_http,
246 handle_https,
247 );
248 };
249
250 eprintln!("You must set key always!! Right or Fake or not!!");
251
252 Ok(())
253 }
254
255 #[must_use]
256 pub fn data<D>(mut self, data: D) -> Self
257 where
258 D: Any + Send + Sync
259 {
260 self.data.insert(data);
261 self
262 }
263}
264
265pub type Request = (http::Request<Body>, bool, Context);
266
267use thiserror::Error;
268#[derive(Error, Debug)]
269pub enum ChiteyError {
270 #[error("extract value failed")]
271 UrlPatternError,
272 #[error("server failed: {0}")]
273 InternalServerError(String),
274 #[error("cannot analyze key: {0}")]
275 KeyAnalyzeError(String),
276 #[error("failed kill server: {0}")]
277 ServerKillError(String),
278}