diff --git a/crates/ptth_file_server_bin/src/lib.rs b/crates/ptth_file_server_bin/src/lib.rs new file mode 100644 index 0000000..3935328 --- /dev/null +++ b/crates/ptth_file_server_bin/src/lib.rs @@ -0,0 +1,127 @@ +#![warn (clippy::pedantic)] + +use std::{ + ffi::OsString, + net::SocketAddr, + path::PathBuf, + sync::Arc, +}; + +use arc_swap::ArcSwap; +use hyper::{ + Body, + Request, + Response, + Server, + service::{ + make_service_fn, + service_fn, + }, + StatusCode, +}; +use serde::Deserialize; +use tokio_stream::wrappers::ReceiverStream; +use tracing::debug; + +use ptth_core::{ + http_serde::RequestParts, + prelude::*, +}; +use ptth_server::{ + file_server::{ + self, + metrics, + FileServer, + }, + load_toml, +}; + +async fn handle_all (req: Request , state: Arc ) +-> anyhow::Result > +{ + use std::str::FromStr; + use hyper::header::HeaderName; + + debug! ("req.uri () = {:?}", req.uri ()); + + let path_and_query = req.uri ().path_and_query ().map_or_else (|| req.uri ().path (), http::uri::PathAndQuery::as_str); + + let path_and_query = path_and_query.into (); + + let (parts, _) = req.into_parts (); + + let ptth_req = RequestParts::from_hyper (parts.method, path_and_query, parts.headers)?; + + let ptth_resp = state.serve_all ( + ptth_req.method, + &ptth_req.uri, + &ptth_req.headers + ).await?; + + let mut resp = Response::builder () + .status (StatusCode::from (ptth_resp.parts.status_code)); + + for (k, v) in ptth_resp.parts.headers { + resp = resp.header (HeaderName::from_str (&k)?, v); + } + + let body = ptth_resp.body.map_or_else (Body::empty, |body| { + Body::wrap_stream (ReceiverStream::new (body)) + }); + + Ok (resp.body (body)?) +} + +#[derive (Deserialize)] +struct ConfigFile { + file_server_root: Option , + name: Option , +} + +pub async fn main (_args: &[OsString]) -> anyhow::Result <()> { + let path = PathBuf::from ("./config/ptth_server.toml"); + let config_file: ConfigFile = load_toml::load (&path)?; + info! ("file_server_root: {:?}", config_file.file_server_root); + + let addr = SocketAddr::from(([0, 0, 0, 0], 4000)); + + let metrics_interval = Arc::new (ArcSwap::default ()); + + let interval_writer = Arc::clone (&metrics_interval); + tokio::spawn (async move { + file_server::metrics::Interval::monitor (interval_writer).await; + }); + + let state = Arc::new (FileServer::new ( + config_file.file_server_root, + &PathBuf::new (), + config_file.name.unwrap_or_else (|| "PTTH File Server".to_string ()), + metrics_interval, + Some (path), + )?); + + let make_svc = make_service_fn (|_conn| { + let state = state.clone (); + + async { + Ok::<_, String> (service_fn (move |req| { + let state = state.clone (); + + handle_all (req, state) + })) + } + }); + + let (shutdown_rx, forced_shutdown) = ptth_core::graceful_shutdown::init_with_force (); + + let server = Server::bind (&addr) + .serve (make_svc) + .with_graceful_shutdown (async move { + shutdown_rx.await.ok (); + }); + + forced_shutdown.wrap_server (server).await??; + + Ok (()) +} + diff --git a/crates/ptth_file_server_bin/src/main.rs b/crates/ptth_file_server_bin/src/main.rs index 1966acb..43c896e 100644 --- a/crates/ptth_file_server_bin/src/main.rs +++ b/crates/ptth_file_server_bin/src/main.rs @@ -1,128 +1,12 @@ -#![warn (clippy::pedantic)] - use std::{ - net::SocketAddr, - path::PathBuf, - sync::Arc, + iter::FromIterator, }; -use arc_swap::ArcSwap; -use hyper::{ - Body, - Request, - Response, - Server, - service::{ - make_service_fn, - service_fn, - }, - StatusCode, -}; -use serde::Deserialize; -use tokio_stream::wrappers::ReceiverStream; -use tracing::debug; - -use ptth_core::{ - http_serde::RequestParts, - prelude::*, -}; -use ptth_server::{ - file_server::{ - self, - metrics, - FileServer, - }, - load_toml, -}; - -async fn handle_all (req: Request , state: Arc ) --> anyhow::Result > -{ - use std::str::FromStr; - use hyper::header::HeaderName; - - debug! ("req.uri () = {:?}", req.uri ()); - - let path_and_query = req.uri ().path_and_query ().map_or_else (|| req.uri ().path (), http::uri::PathAndQuery::as_str); - - let path_and_query = path_and_query.into (); - - let (parts, _) = req.into_parts (); - - let ptth_req = RequestParts::from_hyper (parts.method, path_and_query, parts.headers)?; - - let ptth_resp = state.serve_all ( - ptth_req.method, - &ptth_req.uri, - &ptth_req.headers - ).await?; - - let mut resp = Response::builder () - .status (StatusCode::from (ptth_resp.parts.status_code)); - - for (k, v) in ptth_resp.parts.headers { - resp = resp.header (HeaderName::from_str (&k)?, v); - } - - let body = ptth_resp.body.map_or_else (Body::empty, |body| { - Body::wrap_stream (ReceiverStream::new (body)) - }); - - Ok (resp.body (body)?) -} - -#[derive (Deserialize)] -pub struct ConfigFile { - pub file_server_root: Option , - pub name: Option , -} - #[tokio::main] async fn main () -> anyhow::Result <()> { tracing_subscriber::fmt::init (); - let path = PathBuf::from ("./config/ptth_server.toml"); - let config_file: ConfigFile = load_toml::load (&path)?; - info! ("file_server_root: {:?}", config_file.file_server_root); + let args = Vec::from_iter (std::env::args_os ()); - let addr = SocketAddr::from(([0, 0, 0, 0], 4000)); - - let metrics_interval = Arc::new (ArcSwap::default ()); - - let interval_writer = Arc::clone (&metrics_interval); - tokio::spawn (async move { - file_server::metrics::Interval::monitor (interval_writer).await; - }); - - let state = Arc::new (FileServer::new ( - config_file.file_server_root, - &PathBuf::new (), - config_file.name.unwrap_or_else (|| "PTTH File Server".to_string ()), - metrics_interval, - Some (path), - )?); - - let make_svc = make_service_fn (|_conn| { - let state = state.clone (); - - async { - Ok::<_, String> (service_fn (move |req| { - let state = state.clone (); - - handle_all (req, state) - })) - } - }); - - let (shutdown_rx, forced_shutdown) = ptth_core::graceful_shutdown::init_with_force (); - - let server = Server::bind (&addr) - .serve (make_svc) - .with_graceful_shutdown (async move { - shutdown_rx.await.ok (); - }); - - forced_shutdown.wrap_server (server).await??; - - Ok (()) + ptth_file_server::main (&args).await } diff --git a/crates/ptth_multi_call_server/src/main.rs b/crates/ptth_multi_call_server/src/main.rs index 7349f62..48648fd 100644 --- a/crates/ptth_multi_call_server/src/main.rs +++ b/crates/ptth_multi_call_server/src/main.rs @@ -67,7 +67,7 @@ async fn main () -> anyhow::Result <()> { let (subcommand, args) = parse_args (&args)?; match subcommand { Subcommand::PtthServer => ptth_server::executable::main (&args).await, - Subcommand::PtthFileServer => unimplemented! (), + Subcommand::PtthFileServer => ptth_file_server::main (&args).await, Subcommand::PtthQuicEndServer => quic_demo::executable_end_server::main (&args).await, } }