hyper_static_server/
server.rs1
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 ("&", "&");
99 let _text = _text.replace ("<", "<");
100 let _text = _text.replace (">", ">");
101 let _text = if _quote {
102 _text.replace ("\"", """)
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