diff --git a/crates/ptth_relay/src/lib.rs b/crates/ptth_relay/src/lib.rs index 1c1c7fa..9b5ce9d 100644 --- a/crates/ptth_relay/src/lib.rs +++ b/crates/ptth_relay/src/lib.rs @@ -61,6 +61,7 @@ pub mod git_version; pub mod key_validity; mod relay_state; +mod scraper_api; mod server_endpoint; pub use config::Config; @@ -68,6 +69,7 @@ pub use errors::*; pub use relay_state::RelayState; use relay_state::*; +use scraper_api::*; fn ok_reply > (b: B) -> Result , http::Error> @@ -324,86 +326,6 @@ async fn handle_server_list ( Ok (ok_reply (s)?) } -#[instrument (level = "trace", skip (req, state))] -async fn handle_scraper_api_v1 ( - req: Request , - state: Arc , - path_rest: &str -) --> Result , RequestError> -{ - use key_validity::KeyValidity; - - let api_key = req.headers ().get ("X-ApiKey"); - - let api_key = match api_key { - None => return Ok (error_reply (StatusCode::FORBIDDEN, "Can't run scraper without an API key")?), - Some (x) => x, - }; - - let bad_key = || error_reply (StatusCode::FORBIDDEN, "403 Forbidden"); - - { - let config = state.config.read ().await; - - let dev_mode = match &config.iso.dev_mode { - None => return Ok (bad_key ()?), - Some (x) => x, - }; - - let expected_key = match &dev_mode.scraper_key { - None => return Ok (bad_key ()?), - Some (x) => x, - }; - - let now = chrono::Utc::now (); - - match expected_key.is_valid (now, api_key.as_bytes ()) { - KeyValidity::Valid => (), - KeyValidity::WrongKey (bad_hash) => { - error! ("Bad scraper key with hash {:?}", bad_hash); - return Ok (bad_key ()?); - } - err => { - error! ("Bad scraper key {:?}", err); - return Ok (bad_key ()?); - }, - } - } - - if path_rest == "test" { - Ok (error_reply (StatusCode::OK, "You're valid!")?) - } - else { - Ok (error_reply (StatusCode::NOT_FOUND, "Unknown API endpoint")?) - } -} - -#[instrument (level = "trace", skip (req, state))] -async fn handle_scraper_api ( - req: Request , - state: Arc , - path_rest: &str -) --> Result , RequestError> -{ - { - if ! state.config.read ().await.iso.enable_scraper_auth { - return Ok (error_reply (StatusCode::FORBIDDEN, "Scraper API disabled")?); - } - } - - if let Some (rest) = prefix_match ("v1/", path_rest) { - handle_scraper_api_v1 (req, state, rest).await - } - else if let Some (rest) = prefix_match ("api/", path_rest) { - handle_scraper_api_v1 (req, state, rest).await - } - else { - Ok (error_reply (StatusCode::NOT_FOUND, "Unknown scraper API version")?) - } -} - #[instrument (level = "trace", skip (req, state))] async fn handle_all (req: Request , state: Arc ) -> Result , RequestError> diff --git a/crates/ptth_relay/src/scraper_api.rs b/crates/ptth_relay/src/scraper_api.rs new file mode 100644 index 0000000..b63bbf7 --- /dev/null +++ b/crates/ptth_relay/src/scraper_api.rs @@ -0,0 +1,100 @@ +use std::{ + sync::Arc, +}; + +use hyper::{ + Body, + Request, + Response, + StatusCode, +}; +use tracing::{ + error, + instrument, +}; + +use crate::{ + RequestError, + error_reply, + key_validity::KeyValidity, + prefix_match, + relay_state::RelayState, +}; + +#[instrument (level = "trace", skip (req, state))] +pub async fn handle_scraper_api_v1 ( + req: Request , + state: Arc , + path_rest: &str +) +-> Result , RequestError> +{ + let api_key = req.headers ().get ("X-ApiKey"); + + let api_key = match api_key { + None => return Ok (error_reply (StatusCode::FORBIDDEN, "Can't run scraper without an API key")?), + Some (x) => x, + }; + + let bad_key = || error_reply (StatusCode::FORBIDDEN, "403 Forbidden"); + + { + let config = state.config.read ().await; + + let dev_mode = match &config.iso.dev_mode { + None => return Ok (bad_key ()?), + Some (x) => x, + }; + + let expected_key = match &dev_mode.scraper_key { + None => return Ok (bad_key ()?), + Some (x) => x, + }; + + let now = chrono::Utc::now (); + + match expected_key.is_valid (now, api_key.as_bytes ()) { + KeyValidity::Valid => (), + KeyValidity::WrongKey (bad_hash) => { + error! ("Bad scraper key with hash {:?}", bad_hash); + return Ok (bad_key ()?); + } + err => { + error! ("Bad scraper key {:?}", err); + return Ok (bad_key ()?); + }, + } + } + + if path_rest == "test" { + Ok (error_reply (StatusCode::OK, "You're valid!")?) + } + else { + Ok (error_reply (StatusCode::NOT_FOUND, "Unknown API endpoint")?) + } +} + +#[instrument (level = "trace", skip (req, state))] +pub async fn handle_scraper_api ( + req: Request , + state: Arc , + path_rest: &str +) +-> Result , RequestError> +{ + { + if ! state.config.read ().await.iso.enable_scraper_auth { + return Ok (error_reply (StatusCode::FORBIDDEN, "Scraper API disabled")?); + } + } + + if let Some (rest) = prefix_match ("v1/", path_rest) { + handle_scraper_api_v1 (req, state, rest).await + } + else if let Some (rest) = prefix_match ("api/", path_rest) { + handle_scraper_api_v1 (req, state, rest).await + } + else { + Ok (error_reply (StatusCode::NOT_FOUND, "Unknown scraper API version")?) + } +}