use crate::{ config::GurtConfig, handlers::{FileHandler, DirectoryHandler, DefaultFileHandler, DefaultDirectoryHandler}, request_handler::{RequestHandler, RequestHandlerBuilder}, }; use gurt::prelude::*; use std::{path::PathBuf, sync::Arc}; pub struct FileServerBuilder { config: GurtConfig, file_handler: Arc, directory_handler: Arc, } impl FileServerBuilder { pub fn new(config: GurtConfig) -> Self { Self { config, file_handler: Arc::new(DefaultFileHandler), directory_handler: Arc::new(DefaultDirectoryHandler), } } pub fn with_file_handler(mut self, handler: H) -> Self { self.file_handler = Arc::new(handler); self } pub fn with_directory_handler(mut self, handler: H) -> Self { self.directory_handler = Arc::new(handler); self } pub fn build(self) -> crate::Result { let server = self.create_server()?; let request_handler = self.create_request_handler(); let server_with_routes = self.add_routes(server, request_handler); Ok(server_with_routes) } fn create_server(&self) -> crate::Result { match &self.config.tls { Some(tls) => { println!("TLS using certificate: {}", tls.certificate.display()); GurtServerBuilder::new() .with_tls_certificates(&tls.certificate, &tls.private_key) .with_timeouts( self.config.get_handshake_timeout(), self.config.get_request_timeout(), self.config.get_connection_timeout(), ) .build() } None => { Err(crate::ServerError::TlsConfiguration( "GURT protocol requires TLS encryption. Please provide --cert and --key parameters.".to_string() )) } } } fn create_request_handler(&self) -> RequestHandler { RequestHandlerBuilder::new(&*self.config.server.base_directory) .with_file_handler(DefaultFileHandler) .with_directory_handler(DefaultDirectoryHandler) .with_config(Arc::new(self.config.clone())) .build() } fn add_routes(self, server: GurtServer, request_handler: RequestHandler) -> GurtServer { let request_handler = Arc::new(request_handler); let server = server .get("/", { let handler = request_handler.clone(); move |ctx| { let handler = handler.clone(); let ctx_clone = ctx.clone(); async move { handler.handle_root_request_with_context(ctx_clone).await } } }) .get("/*", { let handler = request_handler.clone(); move |ctx| { let handler = handler.clone(); let path = ctx.path().to_string(); let ctx_clone = ctx.clone(); async move { handler.handle_file_request_with_context(&path, ctx_clone).await } } }); let server = server .post("/", { let handler = request_handler.clone(); move |ctx| { let handler = handler.clone(); let ctx_clone = ctx.clone(); async move { handler.handle_method_request_with_context(ctx_clone).await } } }) .post("/*", { let handler = request_handler.clone(); move |ctx| { let handler = handler.clone(); let ctx_clone = ctx.clone(); async move { handler.handle_method_request_with_context(ctx_clone).await } } }) .put("/", { let handler = request_handler.clone(); move |ctx| { let handler = handler.clone(); let ctx_clone = ctx.clone(); async move { handler.handle_method_request_with_context(ctx_clone).await } } }) .put("/*", { let handler = request_handler.clone(); move |ctx| { let handler = handler.clone(); let ctx_clone = ctx.clone(); async move { handler.handle_method_request_with_context(ctx_clone).await } } }) .delete("/", { let handler = request_handler.clone(); move |ctx| { let handler = handler.clone(); let ctx_clone = ctx.clone(); async move { handler.handle_method_request_with_context(ctx_clone).await } } }) .delete("/*", { let handler = request_handler.clone(); move |ctx| { let handler = handler.clone(); let ctx_clone = ctx.clone(); async move { handler.handle_method_request_with_context(ctx_clone).await } } }) .patch("/", { let handler = request_handler.clone(); move |ctx| { let handler = handler.clone(); let ctx_clone = ctx.clone(); async move { handler.handle_method_request_with_context(ctx_clone).await } } }) .patch("/*", { let handler = request_handler.clone(); move |ctx| { let handler = handler.clone(); let ctx_clone = ctx.clone(); async move { handler.handle_method_request_with_context(ctx_clone).await } } }) .options("/", { let handler = request_handler.clone(); move |ctx| { let handler = handler.clone(); let ctx_clone = ctx.clone(); async move { handler.handle_method_request_with_context(ctx_clone).await } } }) .options("/*", { let handler = request_handler.clone(); move |ctx| { let handler = handler.clone(); let ctx_clone = ctx.clone(); async move { handler.handle_method_request_with_context(ctx_clone).await } } }) .head("/", { let handler = request_handler.clone(); move |ctx| { let handler = handler.clone(); let ctx_clone = ctx.clone(); async move { handler.handle_method_request_with_context(ctx_clone).await } } }) .head("/*", { let handler = request_handler.clone(); move |ctx| { let handler = handler.clone(); let ctx_clone = ctx.clone(); async move { handler.handle_method_request_with_context(ctx_clone).await } } }); server } } pub struct GurtServerBuilder { cert_path: Option, key_path: Option, host: Option, port: Option, handshake_timeout: Option, request_timeout: Option, connection_timeout: Option, } impl GurtServerBuilder { pub fn new() -> Self { Self { cert_path: None, key_path: None, host: None, port: None, handshake_timeout: None, request_timeout: None, connection_timeout: None, } } pub fn with_tls_certificates>(mut self, cert_path: P, key_path: P) -> Self { self.cert_path = Some(cert_path.into()); self.key_path = Some(key_path.into()); self } pub fn with_host>(mut self, host: S) -> Self { self.host = Some(host.into()); self } pub fn with_port(mut self, port: u16) -> Self { self.port = Some(port); self } pub fn with_timeouts(mut self, handshake_timeout: std::time::Duration, request_timeout: std::time::Duration, connection_timeout: std::time::Duration) -> Self { self.handshake_timeout = Some(handshake_timeout); self.request_timeout = Some(request_timeout); self.connection_timeout = Some(connection_timeout); self } pub fn build(self) -> crate::Result { match (self.cert_path, self.key_path) { (Some(cert), Some(key)) => { let mut server = GurtServer::with_tls_certificates( cert.to_str().ok_or_else(|| { crate::ServerError::TlsConfiguration("Invalid certificate path".to_string()) })?, key.to_str().ok_or_else(|| { crate::ServerError::TlsConfiguration("Invalid key path".to_string()) })? ).map_err(crate::ServerError::from)?; if let (Some(handshake), Some(request), Some(connection)) = (self.handshake_timeout, self.request_timeout, self.connection_timeout) { server = server.with_timeouts(handshake, request, connection); } Ok(server) } _ => { Err(crate::ServerError::TlsConfiguration( "TLS certificates are required. Use with_tls_certificates() to provide them.".to_string() )) } } } } impl Default for GurtServerBuilder { fn default() -> Self { Self::new() } }