diff --git a/crates/ptth_file_server_bin/src/main.rs b/crates/ptth_file_server_bin/src/main.rs index 874dd88..1966acb 100644 --- a/crates/ptth_file_server_bin/src/main.rs +++ b/crates/ptth_file_server_bin/src/main.rs @@ -30,12 +30,12 @@ use ptth_server::{ file_server::{ self, metrics, - State, + FileServer, }, load_toml, }; -async fn handle_all (req: Request , state: Arc ) +async fn handle_all (req: Request , state: Arc ) -> anyhow::Result > { use std::str::FromStr; @@ -51,8 +51,7 @@ async fn handle_all (req: Request , state: Arc ) let ptth_req = RequestParts::from_hyper (parts.method, path_and_query, parts.headers)?; - let ptth_resp = file_server::serve_all ( - &state, + let ptth_resp = state.serve_all ( ptth_req.method, &ptth_req.uri, &ptth_req.headers @@ -95,7 +94,7 @@ async fn main () -> anyhow::Result <()> { file_server::metrics::Interval::monitor (interval_writer).await; }); - let state = Arc::new (State::new ( + let state = Arc::new (FileServer::new ( config_file.file_server_root, &PathBuf::new (), config_file.name.unwrap_or_else (|| "PTTH File Server".to_string ()), diff --git a/crates/ptth_server/src/file_server/html.rs b/crates/ptth_server/src/file_server/html.rs index d221058..e1232fc 100644 --- a/crates/ptth_server/src/file_server/html.rs +++ b/crates/ptth_server/src/file_server/html.rs @@ -46,7 +46,7 @@ struct DirEntry { } pub async fn serve_root ( - state: &super::State, + state: &super::FileServer, ) -> Result { #[derive (Serialize)] diff --git a/crates/ptth_server/src/file_server/mod.rs b/crates/ptth_server/src/file_server/mod.rs index dec094a..3ddf654 100644 --- a/crates/ptth_server/src/file_server/mod.rs +++ b/crates/ptth_server/src/file_server/mod.rs @@ -59,7 +59,7 @@ pub struct Config { pub file_server_root: Option , } -pub struct State { +pub struct FileServer { pub config: Config, pub handlebars: handlebars::Handlebars <'static>, pub metrics_startup: metrics::Startup, @@ -67,7 +67,7 @@ pub struct State { pub hidden_path: Option , } -impl State { +impl FileServer { pub fn new ( file_server_root: Option , asset_root: &Path, @@ -332,98 +332,100 @@ async fn stream_file ( } } -/// Top-level request handler for the file server module. -/// -/// Passes a request to the internal file server logic. -/// Returns an HTTP response as HTML or JSON, depending on the request. +impl FileServer { + /// Top-level request handler for the file server module. + /// + /// Passes a request to the internal file server logic. + /// Returns an HTTP response as HTML or JSON, depending on the request. -#[instrument (level = "debug", skip (state, headers))] -pub async fn serve_all ( - state: &State, - method: Method, - uri: &str, - headers: &HashMap > -) --> Result -{ - use internal::{ - OutputFormat, - Response::*, - }; - - fn serve_error >> ( - status_code: StatusCode, - msg: S + #[instrument (level = "debug", skip (self, headers))] + pub async fn serve_all ( + &self, + method: Method, + uri: &str, + headers: &HashMap > ) - -> Response + -> Result { - let mut resp = Response::default (); - resp.status_code (status_code); - resp.body_bytes (msg.into ()); - resp - } - - let default_root = PathBuf::from ("./"); - let root: &std::path::Path = state.config.file_server_root - .as_ref () - .unwrap_or (&default_root); - - Ok (match internal::serve_all (root, method, uri, headers, state.hidden_path.as_deref ()).await? { - Favicon => serve_error (StatusCode::NotFound, "Not found\n"), - Forbidden => serve_error (StatusCode::Forbidden, "403 Forbidden\n"), - MethodNotAllowed => serve_error (StatusCode::MethodNotAllowed, "Unsupported method\n"), - NotFound => serve_error (StatusCode::NotFound, "404 Not Found\nAre you missing a trailing slash?\n"), - RangeNotSatisfiable (file_len) => { - let mut resp = Response::default (); - resp.status_code (StatusCode::RangeNotSatisfiable) - .header ("content-range".to_string (), format! ("bytes */{}", file_len).into_bytes ()); - resp - }, - Redirect (location) => { - let mut resp = Response::default (); - resp.status_code (StatusCode::TemporaryRedirect) - .header ("location".to_string (), location.into_bytes ()); - resp.body_bytes (b"Redirecting...\n".to_vec ()); - resp - }, - InvalidQuery => serve_error (StatusCode::BadRequest, "Query is invalid for this object\n"), + use internal::{ + OutputFormat, + Response::*, + }; - Root => html::serve_root (state).await?, - ServeDir (internal::ServeDirParams { - path, - dir, - format - }) => match format { - OutputFormat::Json => serve_dir_json (dir.into_inner ()).await?, - OutputFormat::Html => html::serve_dir (&state.handlebars, &state.metrics_startup, path.to_string_lossy (), dir.into_inner ()).await?, - }, - ServeFile (internal::ServeFileParams { - file, - send_body, - range, - }) => serve_file (file.into_inner (), send_body, range, headers.get ("if-none-match").map (|v| &v[..])).await?, - MarkdownErr (e) => { - #[cfg (feature = "markdown")] - { - use markdown::Error::*; - let e = e.inner; - let code = match &e { - TooBig => StatusCode::InternalServerError, - //NotMarkdown => serve_error (StatusCode::BadRequest, "File is not Markdown"), - NotUtf8 => StatusCode::BadRequest, - }; - - return Ok (serve_error (code, e.to_string ())); - } + fn serve_error >> ( + status_code: StatusCode, + msg: S + ) + -> Response + { + let mut resp = Response::default (); + resp.status_code (status_code); + resp.body_bytes (msg.into ()); + resp + } + + let default_root = PathBuf::from ("./"); + let root: &std::path::Path = self.config.file_server_root + .as_ref () + .unwrap_or (&default_root); + + Ok (match internal::serve_all (root, method, uri, headers, self.hidden_path.as_deref ()).await? { + Favicon => serve_error (StatusCode::NotFound, "Not found\n"), + Forbidden => serve_error (StatusCode::Forbidden, "403 Forbidden\n"), + MethodNotAllowed => serve_error (StatusCode::MethodNotAllowed, "Unsupported method\n"), + NotFound => serve_error (StatusCode::NotFound, "404 Not Found\nAre you missing a trailing slash?\n"), + RangeNotSatisfiable (file_len) => { + let mut resp = Response::default (); + resp.status_code (StatusCode::RangeNotSatisfiable) + .header ("content-range".to_string (), format! ("bytes */{}", file_len).into_bytes ()); + resp + }, + Redirect (location) => { + let mut resp = Response::default (); + resp.status_code (StatusCode::TemporaryRedirect) + .header ("location".to_string (), location.into_bytes ()); + resp.body_bytes (b"Redirecting...\n".to_vec ()); + resp + }, + InvalidQuery => serve_error (StatusCode::BadRequest, "Query is invalid for this object\n"), - #[cfg (not (feature = "markdown"))] - { - let _e = e; - serve_error (StatusCode::BadRequest, "Markdown feature is disabled") - } - }, - MarkdownPreview (s) => html::serve (s), - }) + Root => html::serve_root (self).await?, + ServeDir (internal::ServeDirParams { + path, + dir, + format + }) => match format { + OutputFormat::Json => serve_dir_json (dir.into_inner ()).await?, + OutputFormat::Html => html::serve_dir (&self.handlebars, &self.metrics_startup, path.to_string_lossy (), dir.into_inner ()).await?, + }, + ServeFile (internal::ServeFileParams { + file, + send_body, + range, + }) => serve_file (file.into_inner (), send_body, range, headers.get ("if-none-match").map (|v| &v[..])).await?, + MarkdownErr (e) => { + #[cfg (feature = "markdown")] + { + use markdown::Error::*; + let e = e.inner; + let code = match &e { + TooBig => StatusCode::InternalServerError, + //NotMarkdown => serve_error (StatusCode::BadRequest, "File is not Markdown"), + NotUtf8 => StatusCode::BadRequest, + }; + + return Ok (serve_error (code, e.to_string ())); + } + + #[cfg (not (feature = "markdown"))] + { + let _e = e; + serve_error (StatusCode::BadRequest, "Markdown feature is disabled") + } + }, + MarkdownPreview (s) => html::serve (s), + }) + } } fn load_templates ( diff --git a/crates/ptth_server/src/lib.rs b/crates/ptth_server/src/lib.rs index 9208a44..94b60a1 100644 --- a/crates/ptth_server/src/lib.rs +++ b/crates/ptth_server/src/lib.rs @@ -46,7 +46,7 @@ pub mod load_toml; use errors::ServerError; struct State { - file_server: file_server::State, + file_server: file_server::FileServer, config: Config, client: Client, } @@ -63,8 +63,7 @@ async fn handle_one_req ( debug! ("Handling request {}", req_id); - let response = file_server::serve_all ( - &state.file_server, + let response = state.file_server.serve_all ( parts.method, &parts.uri, &parts.headers, @@ -253,7 +252,7 @@ pub async fn run_server ( }); let state = Arc::new (State { - file_server: file_server::State::new ( + file_server: file_server::FileServer::new ( config_file.file_server_root, &asset_root, config_file.name,