From 6b71b32cf5c6625a042e108954ffbe2d3fb44b6a Mon Sep 17 00:00:00 2001 From: _ <_@_> Date: Sat, 10 Apr 2021 09:38:53 -0500 Subject: [PATCH] :recycle: refactor: extract routing module --- crates/ptth_relay/src/lib.rs | 153 +++++++++++---------------- crates/ptth_relay/src/routing.rs | 8 +- crates/ptth_relay/src/scraper_api.rs | 2 +- 3 files changed, 67 insertions(+), 96 deletions(-) diff --git a/crates/ptth_relay/src/lib.rs b/crates/ptth_relay/src/lib.rs index 088daa4..c5a1407 100644 --- a/crates/ptth_relay/src/lib.rs +++ b/crates/ptth_relay/src/lib.rs @@ -97,7 +97,7 @@ async fn handle_http_request ( req: http::request::Parts, uri: String, state: Arc , - server_name: String + server_name: &str ) -> Result , http::Error> { @@ -108,7 +108,7 @@ async fn handle_http_request ( { let config = state.config.read ().await; - if ! config.servers.contains_key (&server_name) { + if ! config.servers.contains_key (server_name) { return error_reply (StatusCode::NOT_FOUND, "Unknown server"); } } @@ -124,7 +124,7 @@ async fn handle_http_request ( state.audit_log.push (AuditEvent::new (AuditData::WebClientGet { req_id: req_id.clone (), - server_name: server_name.clone (), + server_name: server_name.to_string (), })).await; trace! ("Created request {}", req_id); @@ -143,7 +143,7 @@ async fn handle_http_request ( req, }; - let new_rendezvous = match request_rendezvous.remove (&server_name) { + let new_rendezvous = match request_rendezvous.remove (server_name) { Some (ParkedClients (mut v)) => { debug! ("Parking request {} ({} already queued)", req_id, v.len ()); v.push (wrapped); @@ -179,7 +179,7 @@ async fn handle_http_request ( }, }; - request_rendezvous.insert (server_name, new_rendezvous); + request_rendezvous.insert (server_name.to_string (), new_rendezvous); } let timeout = tokio::time::sleep (std::time::Duration::from_secs (30)); @@ -470,7 +470,7 @@ async fn handle_endless_source (gib: usize, throttle: Option ) .body (Body::wrap_stream (ReceiverStream::new (rx))) } -async fn handle_gen_scraper_key (state: Arc ) +async fn handle_gen_scraper_key (_state: Arc ) -> Result , http::Error> { let key = ptth_core::gen_key (); @@ -491,97 +491,68 @@ async fn handle_all ( ) -> Result , RequestError> { - let path = req.uri ().path ().to_string (); - //println! ("{}", path); + use routing::Route::*; + // The path is cloned here, so it's okay to consume the request + // later. + let path = req.uri ().path ().to_string (); trace! ("Request path: {}", path); - if req.method () == Method::POST { - // This is stuff the server can use. Clients can't - // POST right now - - return if let Some (request_code) = prefix_match ("/7ZSFUKGV/http_response/", &path) { - let request_code = request_code.into (); - Ok (server_endpoint::handle_response (req, state, request_code).await?) - } - else if path == "/frontend/debug/endless_sink" { - Ok (handle_endless_sink (req).await?) - } - else { - error! ("Can't POST {}", path); - Ok (error_reply (StatusCode::BAD_REQUEST, "Can't POST this")?) - }; - } - - if let Some (listen_code) = prefix_match ("/7ZSFUKGV/http_listen/", &path) { - let api_key = req.headers ().get ("X-ApiKey"); - - let api_key = match api_key { - None => return Ok (error_reply (StatusCode::FORBIDDEN, "Can't run server without an API key")?), - Some (x) => x, - }; - server_endpoint::handle_listen (state, listen_code.into (), api_key.as_bytes ()).await - } - else if let Some (rest) = prefix_match ("/frontend/servers/", &path) { - // DRY T4H76LB3 - - if rest.is_empty () { - Ok (handle_server_list (state, handlebars).await?) - } - else if let Some (idx) = rest.find ('/') { - let listen_code = String::from (&rest [0..idx]); - let path = String::from (&rest [idx..]); + let route = routing::route_url (req.method (), &path); + let response = match route { + ClientAuditLog => handle_audit_log (state, handlebars).await?, + ClientRelayIsUp => error_reply (StatusCode::OK, "Relay is up")?, + ClientServerGet { + listen_code, + path, + } => { let (parts, _) = req.into_parts (); - Ok (handle_http_request (parts, path, state, listen_code).await?) - } - else { - Ok (error_reply (StatusCode::BAD_REQUEST, "Bad URI format")?) - } - } - else if path == "/frontend/unregistered_servers" { - Ok (handle_unregistered_servers (state, handlebars).await?) - } - else if path == "/frontend/audit_log" { - Ok (handle_audit_log (state, handlebars).await?) - } - else if let Some (rest) = prefix_match ("/frontend/debug/", &path) { - if rest.is_empty () { + handle_http_request (parts, path.to_string (), state, listen_code).await? + }, + ClientServerList => handle_server_list (state, handlebars).await?, + ClientUnregisteredServers => handle_unregistered_servers (state, handlebars).await?, + Debug => { let s = handlebars.render ("debug", &())?; - Ok (ok_reply (s)?) - } - else if rest == "endless_source" { - Ok (handle_endless_source (1, None).await?) - } - else if rest == "endless_source_throttled" { - Ok (handle_endless_source (1, Some (1024 / 64)).await?) - } - else if rest == "endless_sink" { - Ok (error_reply (StatusCode::METHOD_NOT_ALLOWED, "Don't GET this URL, POST to it.")?) - } - else if rest == "gen_key" { - Ok (handle_gen_scraper_key (state).await?) - } - else { - Ok (error_reply (StatusCode::NOT_FOUND, "Can't route URL")?) - } - } - else if path == "/" { - let s = handlebars.render ("root", &())?; - Ok (ok_reply (s)?) - } - else if path == "/frontend/relay_up_check" { - Ok (error_reply (StatusCode::OK, "Relay is up")?) - } - else if path == "/frontend/test_mysterious_error" { - Err (RequestError::Mysterious) - } - else if let Some (rest) = prefix_match ("/scraper/", &path) { - scraper_api::handle (req, state, rest).await - } - else { - Ok (error_reply (StatusCode::OK, "Can't route URL")?) - } + ok_reply (s)? + }, + DebugEndlessSink => handle_endless_sink (req).await?, + DebugEndlessSource (throttle) => handle_endless_source (1, throttle).await?, + DebugGenKey => handle_gen_scraper_key (state).await?, + DebugMysteriousError => return Err (RequestError::Mysterious), + ErrorBadUriFormat => error_reply (StatusCode::BAD_REQUEST, "Bad URI format")?, + ErrorCantPost => { + error! ("Can't POST {}", path); + error_reply (StatusCode::BAD_REQUEST, "Can't POST this")? + }, + ErrorMethodNotAllowed => error_reply (StatusCode::METHOD_NOT_ALLOWED, "Method not allowed. Are you POST-ing to a GET-only url, or vice versa?")?, + ErrorRoutingFailed => error_reply (StatusCode::OK, "URL routing failed")?, + Root => { + let s = handlebars.render ("root", &())?; + ok_reply (s)? + }, + Scraper { + rest, + } => scraper_api::handle (req, state, rest).await?, + ServerHttpListen { + listen_code, + } => { + let api_key = req.headers ().get ("X-ApiKey"); + + let api_key = match api_key { + None => return Ok (error_reply (StatusCode::FORBIDDEN, "Can't run server without an API key")?), + Some (x) => x, + }; + server_endpoint::handle_listen (state, listen_code.into (), api_key.as_bytes ()).await? + }, + ServerHttpResponse { + request_code, + } => { + let request_code = request_code.into (); + server_endpoint::handle_response (req, state, request_code).await? + }, + }; + Ok (response) } pub fn load_templates (asset_root: &Path) diff --git a/crates/ptth_relay/src/routing.rs b/crates/ptth_relay/src/routing.rs index 9b81f2a..352debb 100644 --- a/crates/ptth_relay/src/routing.rs +++ b/crates/ptth_relay/src/routing.rs @@ -12,7 +12,7 @@ pub enum Route <'a> { ClientUnregisteredServers, Debug, DebugEndlessSink, - DebugEndlessSource (Option ), + DebugEndlessSource (Option ), DebugGenKey, DebugMysteriousError, ErrorBadUriFormat, @@ -31,7 +31,7 @@ pub enum Route <'a> { }, } -pub fn route_url (method: Method, path: &str) -> Route { +pub fn route_url <'a> (method: &Method, path: &'a str) -> Route <'a> { if method == Method::POST { return if let Some (request_code) = path.strip_prefix ("/7ZSFUKGV/http_response/") { Route::ServerHttpResponse { @@ -124,14 +124,14 @@ mod tests { for (input, expected) in vec! [ ("/", Route::Root), ].into_iter () { - let actual = route_url (Method::GET, input); + let actual = route_url (&Method::GET, input); assert_eq! (actual, expected); } for (input, expected) in vec! [ ("/", Route::ErrorCantPost), ].into_iter () { - let actual = route_url (Method::POST, input); + let actual = route_url (&Method::POST, input); assert_eq! (actual, expected); } } diff --git a/crates/ptth_relay/src/scraper_api.rs b/crates/ptth_relay/src/scraper_api.rs index 9f2c768..a5cbd5f 100644 --- a/crates/ptth_relay/src/scraper_api.rs +++ b/crates/ptth_relay/src/scraper_api.rs @@ -171,7 +171,7 @@ async fn api_v1 ( // This is ugly. I don't like having scraper_api know about the // crate root. - Ok (crate::handle_http_request (parts, path, state, listen_code).await?) + Ok (crate::handle_http_request (parts, path, state, &listen_code).await?) } else { Ok (error_reply (StatusCode::BAD_REQUEST, "Bad URI format")?)