hyper_static_server/
server.rs

1
2
3use crate::hss;
4
5use crate::hss::RequestExt as _;
6use crate::hss::ResponseExtBuild as _;
7
8use crate::StaticRouteDebug;
9
10
11
12
13pub struct StaticHandler {
14	routes : hss::Routes,
15	random_token : String,
16}
17
18
19impl StaticHandler {
20	
21	pub fn new (_routes : hss::Routes) -> Self {
22		Self {
23				routes : _routes,
24				random_token : random_token (),
25			}
26	}
27}
28
29
30
31
32impl StaticHandler {
33	
34	
35	pub fn serve (&self, _request : hss::Request<hss::Body>) -> hss::HandlerFutureDynBox {
36		
37		if ! _request.is_get () {
38			eprintln! ("[ww] [1211a46c]  failing `{}` with 405 (method not allowed)", _request.uri_path ());
39			return hss::Response::new_method_not_allowed () .into ();
40		}
41		
42		if _request.uri_path () .starts_with ("/__/") {
43			return self.serve_special (_request);
44		}
45		
46		#[ cfg (not (feature = "production")) ]
47		eprintln! ("[ii] [9ada1c36]  serving `{}`...", _request.uri_path ());
48		
49		match self.routes.try_handle (_request) {
50			Ok (_future) =>
51				return _future,
52			Err (_request) =>
53				return self.serve_404 (_request),
54		}
55	}
56	
57	
58	pub fn serve_special (&self, _request : hss::Request<hss::Body>) -> hss::HandlerFutureDynBox {
59		
60		match _request.uri_path () {
61			"/__/heartbeat" =>
62				return hss::Response::new_200 () .into (),
63			
64			#[ cfg (not (feature = "production")) ]
65			"/__/reload.txt" =>
66				return hss::Response::new_200_with_text (self.random_token.clone ()) .into (),
67			
68			#[ cfg (not (feature = "production")) ]
69			"/__/reload.js" =>
70				return hss::Response::new_200_with_body (
71						& include_bytes! ("./reload.js") [..],
72						Some (hss::ContentType::Js),
73					) .into (),
74			
75			#[ cfg (not (feature = "production")) ]
76			"/__/routes.html" =>
77				return self.serve_routes_index_html (_request),
78			
79			#[ cfg (not (feature = "production")) ]
80			"/__/routes.txt" =>
81				return self.serve_routes_index_txt (_request),
82			
83			_ =>
84				return self.serve_404 (_request),
85		}
86	}
87	
88	
89	#[ cfg (not (feature = "production")) ]
90	pub fn serve_routes_index_html (&self, _request : hss::Request<hss::Body>) -> hss::HandlerFutureDynBox {
91		
92		let mut _routes : Vec<_> = self.routes.routes () .collect ();
93		_routes.sort_by_key (|_route| &_route.path);
94		
95		let mut _buffer = String::with_capacity (128 * 1024);
96		
97		fn _sanitize (_text : &str, _quote : bool) -> String {
98			let _text = _text.replace ("&", "&amp;");
99			let _text = _text.replace ("<", "&lt;");
100			let _text = _text.replace (">", "&gt;");
101			let _text = if _quote {
102				_text.replace ("\"", "&quot;")
103			} else {
104				_text
105			};
106			return _text;
107		}
108		
109		_buffer.push_str ("<!DOCTYPE html><html lang=\"en\">\n");
110		_buffer.push_str ("<head><title>Vaktundur -- routes</title><script src=\"/__/reload.js\" defer></script></head>\n");
111		_buffer.push_str ("<body><ul>\n");
112		for _route in _routes.into_iter () {
113			_buffer.push_str ("<li><code><a href=\"");
114			_buffer.push_str (& _sanitize (&_route.path, true));
115			_buffer.push_str ("\">");
116			_buffer.push_str (& _sanitize (&_route.path, false));
117			_buffer.push_str ("</a>");
118			if let Some (_debug) = _route.extensions.get::<StaticRouteDebug> () {
119				_buffer.push_str (" -> <span>");
120				_buffer.push_str (& _sanitize (& format! ("{:?}", _debug), false));
121				_buffer.push_str ("</span>");
122			}
123			_buffer.push_str ("</code></li>\n");
124		}
125		_buffer.push_str ("</ul></body>\n");
126		
127		return hss::Response::new_200_with_html (_buffer) .into ();
128	}
129	
130	#[ cfg (not (feature = "production")) ]
131	pub fn serve_routes_index_txt (&self, _request : hss::Request<hss::Body>) -> hss::HandlerFutureDynBox {
132		
133		let mut _routes : Vec<_> = self.routes.routes () .collect ();
134		_routes.sort_by_key (|_route| &_route.path);
135		
136		let mut _buffer = String::with_capacity (128 * 1024);
137		
138		for _route in _routes.into_iter () {
139			_buffer.push_str ("* ");
140			_buffer.push_str (&_route.path);
141			if let Some (_debug) = _route.extensions.get::<StaticRouteDebug> () {
142				_buffer.push_str (" -> ");
143				_buffer.push_str (& format! ("{:?}", _debug));
144			}
145			_buffer.push_str ("\n");
146		}
147		
148		return hss::Response::new_200_with_text (_buffer) .into ();
149	}
150	
151	
152	pub fn serve_404 (&self, _request : hss::Request<hss::Body>) -> hss::HandlerFutureDynBox {
153		eprintln! ("[ee] [4ba52b89]  failing `{}` with 404 (not found)", _request.uri_path ());
154		return hss::Response::new_404 () .into ();
155	}
156}
157
158
159
160
161impl hss::HandlerDyn for StaticHandler {
162	
163	fn handle (&self, _request : hss::Request<hss::Body>) -> hss::HandlerFutureDynBox {
164		return self.serve (_request);
165	}
166}
167
168
169
170
171fn random_token () -> String {
172	let _token = ::rand::random::<u128> ();
173	format! ("{:0x}", _token)
174}
175