diff --git a/crates/ptth_core/Cargo.toml b/crates/ptth_core/Cargo.toml index 7a584a0..937bee2 100644 --- a/crates/ptth_core/Cargo.toml +++ b/crates/ptth_core/Cargo.toml @@ -12,6 +12,7 @@ ctrlc = { version = "3.1.7", features = [ "termination" ] } futures = "0.3.7" hyper = "0.13.8" serde = {version = "1.0.117", features = ["derive"]} +thiserror = "1.0.22" tokio = { version = "0.2.22", features = ["full"] } tracing = "0.1.21" tracing-futures = "0.2.4" diff --git a/crates/ptth_core/src/graceful_shutdown.rs b/crates/ptth_core/src/graceful_shutdown.rs index 82bd541..38e1c36 100644 --- a/crates/ptth_core/src/graceful_shutdown.rs +++ b/crates/ptth_core/src/graceful_shutdown.rs @@ -1,3 +1,6 @@ +// False positive on futures::select! macro +#![allow (clippy::mut_mut)] + use std::{ cell::Cell, time::Duration, @@ -11,6 +14,7 @@ use tokio::{ use crate::prelude::*; +#[must_use] pub fn init () -> oneshot::Receiver <()> { let (tx, rx) = oneshot::channel::<()> (); @@ -44,10 +48,8 @@ use std::{ impl fmt::Display for ShutdownError { fn fmt (&self, f: &mut fmt::Formatter <'_>) -> fmt::Result { - use ShutdownError::*; - let desc = match self { - ForcedShutdown => "Shutdown was forced after a timeout", + ShutdownError::ForcedShutdown => "Shutdown was forced after a timeout", }; write! (f, "{}", desc) @@ -64,6 +66,10 @@ pub struct ForcedShutdown { } impl ForcedShutdown { + /// # Errors + /// + /// `ForcedShutdown` if the graceful shutdown doesn't complete in time + pub async fn wrap_server < T, F: Future @@ -91,6 +97,7 @@ impl ForcedShutdown { } } +#[must_use] pub fn init_with_force () -> (oneshot::Receiver <()>, ForcedShutdown) { let (tx, rx) = oneshot::channel (); diff --git a/crates/ptth_core/src/http_serde.rs b/crates/ptth_core/src/http_serde.rs index b2d4970..bcbe3ba 100644 --- a/crates/ptth_core/src/http_serde.rs +++ b/crates/ptth_core/src/http_serde.rs @@ -1,23 +1,19 @@ use std::{ - collections::*, + collections::HashMap, convert::{TryFrom, TryInto}, }; use serde::{Deserialize, Serialize}; +use thiserror::Error; use tokio::sync::mpsc; // Hyper doesn't seem to make it easy to de/ser requests // and responses and stuff like that, so I do it by hand here. +#[derive (Debug, Error)] pub enum Error { + #[error ("Unsupported method")] UnsupportedMethod, - InvalidHeaderName, -} - -impl From for Error { - fn from (_x: hyper::header::InvalidHeaderName) -> Self { - Self::InvalidHeaderName - } } #[derive (Debug, Deserialize, Serialize)] @@ -56,6 +52,10 @@ pub struct RequestParts { } impl RequestParts { + /// # Errors + /// + /// `UnsupportedMethod` if PTTH doesn't support the method + pub fn from_hyper ( method: hyper::Method, uri: String, @@ -67,8 +67,10 @@ impl RequestParts { let method = Method::try_from (method)?; let headers = HashMap::from_iter ( headers.into_iter () - .filter_map (|(k, v)| k.map (|k| (k, v))) - .map (|(k, v)| (String::from (k.as_str ()), v.as_bytes ().to_vec ())) + .filter_map (|(k, v)| { + let (k, v) = k.map (|k| (k, v))?; + Some ((String::from (k.as_str ()), v.as_bytes ().to_vec ())) + }) ); Ok (Self { diff --git a/crates/ptth_core/src/lib.rs b/crates/ptth_core/src/lib.rs index dd92c18..69bd7d6 100644 --- a/crates/ptth_core/src/lib.rs +++ b/crates/ptth_core/src/lib.rs @@ -1,3 +1,5 @@ +#![warn (clippy::pedantic)] + pub mod graceful_shutdown; pub mod http_serde; pub mod prelude; @@ -12,6 +14,7 @@ pub const PTTH_MAGIC_HEADER: &str = "X-PTTH-2LJYXWC4"; // The arguments are in order so they are in order overall: // e.g. prefix_match ("/prefix", "/prefix/middle/suffix") -> "/middle/suffix" +#[must_use] pub fn prefix_match <'a> (prefix: &str, hay: &'a str) -> Option <&'a str> { if hay.starts_with (prefix) { diff --git a/crates/ptth_relay/src/lib.rs b/crates/ptth_relay/src/lib.rs index 25247fd..1b94650 100644 --- a/crates/ptth_relay/src/lib.rs +++ b/crates/ptth_relay/src/lib.rs @@ -305,7 +305,7 @@ async fn handle_http_response ( futures::select! { x = body_tx.send (item).fuse () => if let Err (_) = x { info! ("Body closed while relaying. (Client hung up?)"); - body_finished_tx.send (ClientDisconnected).map_err (|_| LostServer).unwrap (); + body_finished_tx.send (ClientDisconnected).map_err (|_| LostServer)?; break; }, _ = shutdown_watch_rx.recv ().fuse () => { @@ -316,7 +316,7 @@ async fn handle_http_response ( } else { debug! ("Finished relaying bytes"); - body_finished_tx.send (StreamFinished).map_err (|_| LostServer).unwrap (); + body_finished_tx.send (StreamFinished).map_err (|_| LostServer)?; break; } } @@ -324,6 +324,8 @@ async fn handle_http_response ( else { debug! ("Can't relay bytes, relay is shutting down"); } + + Ok::<(), HandleHttpResponseError> (()) }); let body = Body::wrap_stream (body_rx); @@ -346,7 +348,7 @@ async fn handle_http_response ( return Ok (error_reply (StatusCode::BAD_GATEWAY, msg)?); } - relay_task.await?; + relay_task.await??; debug! ("Connected server to client for streaming."); match body_finished_rx.await { diff --git a/crates/ptth_relay/src/main.rs b/crates/ptth_relay/src/main.rs index 009d704..c8d1bce 100644 --- a/crates/ptth_relay/src/main.rs +++ b/crates/ptth_relay/src/main.rs @@ -1,3 +1,5 @@ +#![warn (clippy::pedantic)] + use std::{ convert::TryFrom, error::Error, diff --git a/crates/ptth_server/Cargo.toml b/crates/ptth_server/Cargo.toml index 77004a9..7fc1b84 100644 --- a/crates/ptth_server/Cargo.toml +++ b/crates/ptth_server/Cargo.toml @@ -13,6 +13,7 @@ base64 = "0.12.3" blake3 = "0.3.7" futures = "0.3.7" handlebars = "3.5.1" +http = "0.2.1" hyper = "0.13.8" lazy_static = "1.4.0" percent-encoding = "2.1.0" diff --git a/crates/ptth_server/src/bin/ptth_file_server.rs b/crates/ptth_server/src/bin/ptth_file_server.rs index aefba3a..1080286 100644 --- a/crates/ptth_server/src/bin/ptth_file_server.rs +++ b/crates/ptth_server/src/bin/ptth_file_server.rs @@ -1,3 +1,5 @@ +#![warn (clippy::pedantic)] + use std::{ error::Error, net::SocketAddr, @@ -40,12 +42,6 @@ struct ServerState <'a> { hidden_path: Option , } -fn status_reply > (status: StatusCode, b: B) --> Result , hyper::http::Error> -{ - Response::builder ().status (status).body (b.into ()) -} - async fn handle_all (req: Request , state: Arc >) -> Result , ServerError> { @@ -53,16 +49,13 @@ async fn handle_all (req: Request , state: Arc >) debug! ("req.uri () = {:?}", req.uri ()); - let path_and_query = req.uri ().path_and_query ().map (|x| x.as_str ()).unwrap_or_else (|| req.uri ().path ()); + 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 = match RequestParts::from_hyper (parts.method, path_and_query, parts.headers) { - Ok (x) => x, - _ => return Ok (status_reply (StatusCode::BAD_REQUEST, "Bad request")?), - }; + let ptth_req = RequestParts::from_hyper (parts.method, path_and_query, parts.headers)?; let default_root = PathBuf::from ("./"); let file_server_root: &std::path::Path = state.config.file_server_root @@ -82,14 +75,11 @@ async fn handle_all (req: Request , state: Arc >) let mut resp = Response::builder () .status (StatusCode::from (ptth_resp.parts.status_code)); - for (k, v) in ptth_resp.parts.headers.into_iter () { + for (k, v) in ptth_resp.parts.headers { resp = resp.header (hyper::header::HeaderName::from_str (&k)?, v); } - let body = ptth_resp.body - .map (Body::wrap_stream) - .unwrap_or_else (Body::empty) - ; + let body = ptth_resp.body.map_or_else (Body::empty, Body::wrap_stream); Ok (resp.body (body)?) } diff --git a/crates/ptth_server/src/bin/ptth_server.rs b/crates/ptth_server/src/bin/ptth_server.rs index 2718074..f08361e 100644 --- a/crates/ptth_server/src/bin/ptth_server.rs +++ b/crates/ptth_server/src/bin/ptth_server.rs @@ -1,3 +1,5 @@ +#![warn (clippy::pedantic)] + use std::{ error::Error, path::PathBuf, diff --git a/crates/ptth_server/src/errors.rs b/crates/ptth_server/src/errors.rs index 5708af7..c8c2d4b 100644 --- a/crates/ptth_server/src/errors.rs +++ b/crates/ptth_server/src/errors.rs @@ -13,4 +13,7 @@ pub enum ServerError { #[error ("Can't parse wrapped requests")] CantParseWrappedRequests (rmp_serde::decode::Error), + + #[error ("Can't convert Hyper request to PTTH request")] + CantConvertHyperToPtth (#[from] ptth_core::http_serde::Error), }