From 558c4078fd6b5c10bfbcac826774335904807e39 Mon Sep 17 00:00:00 2001 From: Vika Date: Sat, 28 May 2022 21:05:19 +0300 Subject: feat: group endpoints under `.kittybox` Actually got the idea from https://xeiaso.net/, who groups xer website's endpoints under the `.within` folder. --- kittybox-rs/src/frontend/onboarding.js | 2 +- kittybox-rs/src/main.rs | 101 +++++++++++++-------------------- 2 files changed, 42 insertions(+), 61 deletions(-) (limited to 'kittybox-rs/src') diff --git a/kittybox-rs/src/frontend/onboarding.js b/kittybox-rs/src/frontend/onboarding.js index 89ad84a..c5a1481 100644 --- a/kittybox-rs/src/frontend/onboarding.js +++ b/kittybox-rs/src/frontend/onboarding.js @@ -75,7 +75,7 @@ form.onsubmit = async (event) => { }).filter(feed => feed.name == "" || feed.slug == "") }; - await fetch("/onboarding", { + await fetch("/.kittybox/onboarding", { method: "POST", body: JSON.stringify(json), headers: { "Content-Type": "application/json" } diff --git a/kittybox-rs/src/main.rs b/kittybox-rs/src/main.rs index eb70885..fd1875c 100644 --- a/kittybox-rs/src/main.rs +++ b/kittybox-rs/src/main.rs @@ -25,6 +25,7 @@ async fn main() { std::process::exit(1); } }; + let token_endpoint: Url = match env::var("TOKEN_ENDPOINT") { Ok(val) => { debug!("Token endpoint: {}", val); @@ -41,6 +42,7 @@ async fn main() { std::process::exit(1) } }; + let authorization_endpoint: Url = match env::var("AUTHORIZATION_ENDPOINT") { Ok(val) => { debug!("Auth endpoint: {}", val); @@ -58,32 +60,6 @@ async fn main() { } }; - //let internal_token: Option = env::var("KITTYBOX_INTERNAL_TOKEN").ok(); - - /*let cookie_secret: String = match env::var("COOKIE_SECRET").ok() { - Some(value) => value, - None => { - if let Ok(filename) = env::var("COOKIE_SECRET_FILE") { - use tokio::io::AsyncReadExt; - - let mut file = tokio::fs::File::open(filename).await.map_err(|e| { - error!("Couldn't open the cookie secret file: {}", e); - std::process::exit(1); - }).unwrap(); - let mut temp_string = String::new(); - file.read_to_string(&mut temp_string).await.map_err(|e| { - error!("Couldn't read the cookie secret from file: {}", e); - std::process::exit(1); - }).unwrap(); - - temp_string - } else { - error!("COOKIE_SECRET or COOKIE_SECRET_FILE is not set, will not be able to log in users securely!"); - std::process::exit(1); - } - } - };*/ - let listen_at = match env::var("SERVE_AT") .ok() .unwrap_or_else(|| "[::]:8080".to_string()) @@ -115,7 +91,6 @@ async fn main() { println!("The Redis backend is deprecated."); std::process::exit(1); } else if backend_uri.starts_with("file") { - let database = { let folder = backend_uri.strip_prefix("file://").unwrap(); let path = std::path::PathBuf::from(folder); @@ -138,14 +113,6 @@ async fn main() { let homepage = warp::get() .and(warp::path::end()) .and(kittybox::frontend::homepage(database.clone(), endpoints.clone())); - - let onboarding = warp::path("onboarding") - .and(warp::path::end()) - .and(kittybox::frontend::onboarding( - database.clone(), - endpoints.clone(), - http.clone() - )); let micropub = warp::path("micropub") .and(warp::path::end() @@ -159,68 +126,82 @@ async fn main() { .and(warp::path::end()) .map(|| warp::reply::html(kittybox::MICROPUB_CLIENT)))); + let static_files = warp::path("static") + .and(kittybox::frontend::static_files()); + let media = warp::path("media") .and(warp::path::end() .and(kittybox::media::media()) .or(kittybox::util::require_host() .and(warp::path::param()) .map(|_host: Authority, path: String| format!("media file {}", path)))); - - // TODO remember how login logic works because I forgor - let login = warp::path("login") - .and(warp::path("callback") - .map(|| "callback!") - // TODO form on GET and handler on POST - .or(warp::path::end().map(|| "login page!"))); + + let technical = warp::path(".kittybox") + .and(warp::path("onboarding") + .and(warp::path::end()) + .and(kittybox::frontend::onboarding( + database.clone(), + endpoints.clone(), + http.clone() + )) + .or(warp::path("health") + .and(warp::path::end()) + .and(warp::get()) + // TODO make healthcheck report on database status too + .map(|| "OK")) + .or(warp::path("metrics") + .and(warp::path::end()) + .and(warp::get()) + .map(kittybox::metrics::gather)) + .or(micropub) + .or(media) + .or(static_files) + .or(warp::path("login") + .and(warp::path("callback") + .map(|| "callback!") + // TODO form on GET and handler on POST + .or(warp::path::end() + .map(|| "login page!")) + ) + ) + ); // TODO prettier error response let coffee = warp::path("coffee") .map(|| warp::reply::with_status("I'm a teapot!", warp::http::StatusCode::IM_A_TEAPOT)); - let static_files = warp::path("static") - .and(kittybox::frontend::static_files()); - let catchall = kittybox::frontend::catchall( database.clone(), endpoints.clone() ); - let health = warp::path("health").and(warp::path::end()).map(|| "OK"); - let metrics = warp::path("metrics").and(warp::path::end()).map(kittybox::metrics::gather); - let app = homepage - .or(onboarding) - .or(metrics - .or(health)) - .or(static_files) - .or(login) + .or(technical) .or(coffee) - .or(micropub) - .or(media) .or(catchall) .with(warp::log("kittybox")) .with(kittybox::metrics::metrics(vec![ - "health".to_string(), - "micropub".to_string(), - "static".to_string(), - "media".to_string(), - "metrics".to_string() + ".kittybox".to_string() ])) ; let svc = warp::service(app); + // A little dance to turn a potential file descriptor into an async network socket let mut listenfd = listenfd::ListenFd::from_env(); let tcp_listener: std::net::TcpListener = if let Ok(Some(listener)) = listenfd.take_tcp_listener(0) { listener } else { std::net::TcpListener::bind(listen_at).unwrap() }; + // Set the socket to non-blocking so tokio can work with it properly + // This is the async magic tcp_listener.set_nonblocking(true).unwrap(); info!("Listening on {}", tcp_listener.local_addr().unwrap()); let server = hyper::server::Server::from_tcp(tcp_listener) .unwrap() + // Otherwise Chrome keeps connections open for too long .tcp_keepalive(Some(Duration::from_secs(30 * 60))) .serve(hyper::service::make_service_fn(move |_| { let service = svc.clone(); -- cgit 1.4.1