301 lines
10 KiB
Rust
301 lines
10 KiB
Rust
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<dyn FileHandler>,
|
|
directory_handler: Arc<dyn DirectoryHandler>,
|
|
}
|
|
|
|
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<H: FileHandler + 'static>(mut self, handler: H) -> Self {
|
|
self.file_handler = Arc::new(handler);
|
|
self
|
|
}
|
|
|
|
pub fn with_directory_handler<H: DirectoryHandler + 'static>(mut self, handler: H) -> Self {
|
|
self.directory_handler = Arc::new(handler);
|
|
self
|
|
}
|
|
|
|
pub fn build(self) -> crate::Result<GurtServer> {
|
|
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<GurtServer> {
|
|
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<PathBuf>,
|
|
key_path: Option<PathBuf>,
|
|
host: Option<String>,
|
|
port: Option<u16>,
|
|
handshake_timeout: Option<std::time::Duration>,
|
|
request_timeout: Option<std::time::Duration>,
|
|
connection_timeout: Option<std::time::Duration>,
|
|
}
|
|
|
|
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<P: Into<PathBuf>>(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<S: Into<String>>(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<GurtServer> {
|
|
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()
|
|
}
|
|
} |