Skip to main content

gurty_cli/
server.rs

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}