ptth/crates/ptth_relay/src/routing.rs

164 lines
3.6 KiB
Rust

use hyper::Method;
#[derive (Debug, PartialEq)]
pub enum Route <'a> {
ClientAuditLog,
ClientRelayIsUp,
ClientServerGet {
listen_code: &'a str,
path: &'a str,
},
ClientServerList,
ClientUnregisteredServers,
Debug,
DebugEndlessSink,
DebugEndlessSource (Option <usize>),
DebugGenKey,
DebugMysteriousError,
RegisterServer,
Root,
Scraper {
rest: &'a str,
},
ServerHttpListen {
listen_code: &'a str
},
ServerHttpResponse {
request_code: &'a str,
},
}
#[derive (Debug, PartialEq)]
pub enum Error {
BadUriFormat,
MethodNotAllowed,
NotFound,
}
pub fn route_url <'a> (method: &Method, path: &'a str) -> Result <Route <'a>, Error> {
if let Some (listen_code) = path.strip_prefix ("/7ZSFUKGV/http_listen/") {
assert_method (method, Method::GET)?;
Ok (Route::ServerHttpListen {
listen_code
})
}
else if let Some (request_code) = path.strip_prefix ("/7ZSFUKGV/http_response/") {
assert_method (method, Method::POST)?;
Ok (Route::ServerHttpResponse {
request_code
})
}
else if path == "/frontend/register" {
assert_method (method, Method::POST)?;
Ok (Route::RegisterServer)
}
else if let Some (rest) = path.strip_prefix ("/frontend/servers/") {
// DRY T4H76LB3
if rest.is_empty () {
assert_method (method, Method::GET)?;
Ok (Route::ClientServerList)
}
else if let Some (idx) = rest.find ('/') {
let listen_code = &rest [0..idx];
Ok (Route::ClientServerGet {
listen_code,
path: &rest [idx..],
})
}
else {
assert_method (method, Method::GET)?;
Err (Error::BadUriFormat)
}
}
else if path == "/frontend/unregistered_servers" {
assert_method (method, Method::GET)?;
Ok (Route::ClientUnregisteredServers)
}
else if path == "/frontend/audit_log" {
assert_method (method, Method::GET)?;
Ok (Route::ClientAuditLog)
}
else if let Some (rest) = path.strip_prefix ("/frontend/debug/") {
if rest.is_empty () {
assert_method (method, Method::GET)?;
Ok (Route::Debug)
}
else if rest == "endless_source" {
assert_method (method, Method::GET)?;
Ok (Route::DebugEndlessSource (None))
}
else if rest == "endless_source_throttled" {
assert_method (method, Method::GET)?;
Ok (Route::DebugEndlessSource (Some (1024 / 64)))
}
else if rest == "endless_sink" {
assert_method (method, Method::POST)?;
Ok (Route::DebugEndlessSink)
}
else if rest == "gen_key" {
assert_method (method, Method::GET)?;
Ok (Route::DebugGenKey)
}
else {
Err (Error::NotFound)
}
}
else if path == "/" {
assert_method (method, Method::GET)?;
Ok (Route::Root)
}
else if path == "/frontend/relay_up_check" {
assert_method (method, Method::GET)?;
Ok (Route::ClientRelayIsUp)
}
else if path == "/frontend/test_mysterious_error" {
assert_method (method, Method::GET)?;
Ok (Route::DebugMysteriousError)
}
else if let Some (rest) = path.strip_prefix ("/scraper/") {
assert_method (method, Method::GET)?;
Ok (Route::Scraper {
rest
})
}
else {
tracing::error! ("URL routing failed for `{}`", path);
Err (Error::NotFound)
}
}
fn assert_method <M: PartialEq <Method>> (method: M, expected: Method) -> Result <(), Error>
{
if method == expected {
Ok (())
}
else {
Err (Error::MethodNotAllowed)
}
}
#[cfg (test)]
mod tests {
use super::*;
#[test]
fn routing () {
for (input, expected) in vec! [
("/", Ok (Route::Root)),
].into_iter () {
let actual = route_url (&Method::GET, input);
assert_eq! (actual, expected);
}
for (input, expected) in vec! [
("/", Err (Error::MethodNotAllowed)),
].into_iter () {
let actual = route_url (&Method::POST, input);
assert_eq! (actual, expected);
}
}
}