1use crate::{
2 config::GurtConfig,
3 handlers::{FileHandler, DirectoryHandler, DefaultFileHandler, DefaultDirectoryHandler},
4 request_handler::{RequestHandler, RequestHandlerBuilder},
5};
6use gurtlib::prelude::*;
7use std::{path::PathBuf, sync::Arc};
8
9pub struct FileServerBuilder {
10 config: GurtConfig,
11 file_handler: Arc<dyn FileHandler>,
12 directory_handler: Arc<dyn DirectoryHandler>,
13}
14
15impl FileServerBuilder {
16 pub fn new(config: GurtConfig) -> Self {
17 Self {
18 config,
19 file_handler: Arc::new(DefaultFileHandler),
20 directory_handler: Arc::new(DefaultDirectoryHandler),
21 }
22 }
23
24 pub fn with_file_handler<H: FileHandler + 'static>(mut self, handler: H) -> Self {
25 self.file_handler = Arc::new(handler);
26 self
27 }
28
29 pub fn with_directory_handler<H: DirectoryHandler + 'static>(mut self, handler: H) -> Self {
30 self.directory_handler = Arc::new(handler);
31 self
32 }
33
34 pub fn build(self) -> crate::Result<GurtServer> {
35 let server = self.create_server()?;
36 let request_handler = self.create_request_handler();
37 let server_with_routes = self.add_routes(server, request_handler);
38 Ok(server_with_routes)
39 }
40
41 fn create_server(&self) -> crate::Result<GurtServer> {
42 match &self.config.tls {
43 Some(tls) => {
44 println!("TLS using certificate: {}", tls.certificate.display());
45 GurtServerBuilder::new()
46 .with_tls_certificates(&tls.certificate, &tls.private_key)
47 .with_timeouts(
48 self.config.get_handshake_timeout(),
49 self.config.get_request_timeout(),
50 self.config.get_connection_timeout(),
51 )
52 .build()
53 }
54 None => {
55 Err(crate::ServerError::TlsConfiguration(
56 "GURT protocol requires TLS encryption. Please provide --cert and --key parameters.".to_string()
57 ))
58 }
59 }
60 }
61
62 fn create_request_handler(&self) -> RequestHandler {
63 RequestHandlerBuilder::new(&*self.config.server.base_directory)
64 .with_file_handler(DefaultFileHandler)
65 .with_directory_handler(DefaultDirectoryHandler)
66 .with_config(Arc::new(self.config.clone()))
67 .build()
68 }
69
70 fn add_routes(self, server: GurtServer, request_handler: RequestHandler) -> GurtServer {
71 let request_handler = Arc::new(request_handler);
72
73 let server = server
74 .get("/", {
75 let handler = request_handler.clone();
76 move |ctx| {
77 let handler = handler.clone();
78 let ctx_clone = ctx.clone();
79 async move {
80 handler.handle_root_request_with_context(ctx_clone).await
81 }
82 }
83 })
84 .get("/*", {
85 let handler = request_handler.clone();
86 move |ctx| {
87 let handler = handler.clone();
88 let path = ctx.path().to_string();
89 let ctx_clone = ctx.clone();
90 async move {
91 handler.handle_file_request_with_context(&path, ctx_clone).await
92 }
93 }
94 });
95
96 let server = server
97 .post("/", {
98 let handler = request_handler.clone();
99 move |ctx| {
100 let handler = handler.clone();
101 let ctx_clone = ctx.clone();
102 async move {
103 handler.handle_method_request_with_context(ctx_clone).await
104 }
105 }
106 })
107 .post("/*", {
108 let handler = request_handler.clone();
109 move |ctx| {
110 let handler = handler.clone();
111 let ctx_clone = ctx.clone();
112 async move {
113 handler.handle_method_request_with_context(ctx_clone).await
114 }
115 }
116 })
117 .put("/", {
118 let handler = request_handler.clone();
119 move |ctx| {
120 let handler = handler.clone();
121 let ctx_clone = ctx.clone();
122 async move {
123 handler.handle_method_request_with_context(ctx_clone).await
124 }
125 }
126 })
127 .put("/*", {
128 let handler = request_handler.clone();
129 move |ctx| {
130 let handler = handler.clone();
131 let ctx_clone = ctx.clone();
132 async move {
133 handler.handle_method_request_with_context(ctx_clone).await
134 }
135 }
136 })
137 .delete("/", {
138 let handler = request_handler.clone();
139 move |ctx| {
140 let handler = handler.clone();
141 let ctx_clone = ctx.clone();
142 async move {
143 handler.handle_method_request_with_context(ctx_clone).await
144 }
145 }
146 })
147 .delete("/*", {
148 let handler = request_handler.clone();
149 move |ctx| {
150 let handler = handler.clone();
151 let ctx_clone = ctx.clone();
152 async move {
153 handler.handle_method_request_with_context(ctx_clone).await
154 }
155 }
156 })
157 .patch("/", {
158 let handler = request_handler.clone();
159 move |ctx| {
160 let handler = handler.clone();
161 let ctx_clone = ctx.clone();
162 async move {
163 handler.handle_method_request_with_context(ctx_clone).await
164 }
165 }
166 })
167 .patch("/*", {
168 let handler = request_handler.clone();
169 move |ctx| {
170 let handler = handler.clone();
171 let ctx_clone = ctx.clone();
172 async move {
173 handler.handle_method_request_with_context(ctx_clone).await
174 }
175 }
176 })
177 .options("/", {
178 let handler = request_handler.clone();
179 move |ctx| {
180 let handler = handler.clone();
181 let ctx_clone = ctx.clone();
182 async move {
183 handler.handle_method_request_with_context(ctx_clone).await
184 }
185 }
186 })
187 .options("/*", {
188 let handler = request_handler.clone();
189 move |ctx| {
190 let handler = handler.clone();
191 let ctx_clone = ctx.clone();
192 async move {
193 handler.handle_method_request_with_context(ctx_clone).await
194 }
195 }
196 })
197 .head("/", {
198 let handler = request_handler.clone();
199 move |ctx| {
200 let handler = handler.clone();
201 let ctx_clone = ctx.clone();
202 async move {
203 handler.handle_method_request_with_context(ctx_clone).await
204 }
205 }
206 })
207 .head("/*", {
208 let handler = request_handler.clone();
209 move |ctx| {
210 let handler = handler.clone();
211 let ctx_clone = ctx.clone();
212 async move {
213 handler.handle_method_request_with_context(ctx_clone).await
214 }
215 }
216 });
217
218 server
219 }
220}
221
222
223pub struct GurtServerBuilder {
224 cert_path: Option<PathBuf>,
225 key_path: Option<PathBuf>,
226 host: Option<String>,
227 port: Option<u16>,
228 handshake_timeout: Option<std::time::Duration>,
229 request_timeout: Option<std::time::Duration>,
230 connection_timeout: Option<std::time::Duration>,
231}
232
233impl GurtServerBuilder {
234 pub fn new() -> Self {
235 Self {
236 cert_path: None,
237 key_path: None,
238 host: None,
239 port: None,
240 handshake_timeout: None,
241 request_timeout: None,
242 connection_timeout: None,
243 }
244 }
245
246 pub fn with_tls_certificates<P: Into<PathBuf>>(mut self, cert_path: P, key_path: P) -> Self {
247 self.cert_path = Some(cert_path.into());
248 self.key_path = Some(key_path.into());
249 self
250 }
251
252 pub fn with_host<S: Into<String>>(mut self, host: S) -> Self {
253 self.host = Some(host.into());
254 self
255 }
256
257 pub fn with_port(mut self, port: u16) -> Self {
258 self.port = Some(port);
259 self
260 }
261
262 pub fn with_timeouts(mut self, handshake_timeout: std::time::Duration, request_timeout: std::time::Duration, connection_timeout: std::time::Duration) -> Self {
263 self.handshake_timeout = Some(handshake_timeout);
264 self.request_timeout = Some(request_timeout);
265 self.connection_timeout = Some(connection_timeout);
266 self
267 }
268
269 pub fn build(self) -> crate::Result<GurtServer> {
270 match (self.cert_path, self.key_path) {
271 (Some(cert), Some(key)) => {
272 let mut server = GurtServer::with_tls_certificates(
273 cert.to_str().ok_or_else(|| {
274 crate::ServerError::TlsConfiguration("Invalid certificate path".to_string())
275 })?,
276 key.to_str().ok_or_else(|| {
277 crate::ServerError::TlsConfiguration("Invalid key path".to_string())
278 })?
279 ).map_err(crate::ServerError::from)?;
280
281 if let (Some(handshake), Some(request), Some(connection)) =
282 (self.handshake_timeout, self.request_timeout, self.connection_timeout) {
283 server = server.with_timeouts(handshake, request, connection);
284 }
285
286 Ok(server)
287 }
288 _ => {
289 Err(crate::ServerError::TlsConfiguration(
290 "TLS certificates are required. Use with_tls_certificates() to provide them.".to_string()
291 ))
292 }
293 }
294 }
295}
296
297impl Default for GurtServerBuilder {
298 fn default() -> Self {
299 Self::new()
300 }
301}