From 5610a5f0bf1a9df02bd3d5b55e2cdebef2440360 Mon Sep 17 00:00:00 2001 From: Vika Date: Tue, 24 May 2022 17:18:30 +0300 Subject: flake.nix: reorganize - Kittybox's source code is moved to a subfolder - This improves build caching by Nix since it doesn't take changes to other files into account - Package and test definitions were spun into separate files - This makes my flake.nix much easier to navigate - This also makes it somewhat possible to use without flakes (but it is still not easy, so use flakes!) - Some attributes were moved in compliance with Nix 2.8's changes to flake schema --- src/main.rs | 256 ------------------------------------------------------------ 1 file changed, 256 deletions(-) delete mode 100644 src/main.rs (limited to 'src/main.rs') diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index eb70885..0000000 --- a/src/main.rs +++ /dev/null @@ -1,256 +0,0 @@ -use log::{debug, error, info}; -use std::{convert::Infallible, env, time::Duration}; -use url::Url; -use warp::{Filter, host::Authority}; - -#[tokio::main] -async fn main() { - // TODO turn into a feature so I can enable and disable it - #[cfg(debug_assertions)] - console_subscriber::init(); - - // TODO use tracing instead of log - let logger_env = env_logger::Env::new().filter_or("RUST_LOG", "info"); - env_logger::init_from_env(logger_env); - - info!("Starting the kittybox server..."); - - let backend_uri: String = match env::var("BACKEND_URI") { - Ok(val) => { - debug!("Backend URI: {}", val); - val - } - Err(_) => { - error!("BACKEND_URI is not set, cannot find a database"); - std::process::exit(1); - } - }; - let token_endpoint: Url = match env::var("TOKEN_ENDPOINT") { - Ok(val) => { - debug!("Token endpoint: {}", val); - match Url::parse(&val) { - Ok(val) => val, - _ => { - error!("Token endpoint URL cannot be parsed, aborting."); - std::process::exit(1) - } - } - } - Err(_) => { - error!("TOKEN_ENDPOINT is not set, will not be able to authorize users!"); - std::process::exit(1) - } - }; - let authorization_endpoint: Url = match env::var("AUTHORIZATION_ENDPOINT") { - Ok(val) => { - debug!("Auth endpoint: {}", val); - match Url::parse(&val) { - Ok(val) => val, - _ => { - error!("Authorization endpoint URL cannot be parsed, aborting."); - std::process::exit(1) - } - } - } - Err(_) => { - error!("AUTHORIZATION_ENDPOINT is not set, will not be able to confirm token and ID requests using IndieAuth!"); - std::process::exit(1) - } - }; - - //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()) - .parse::() { - Ok(addr) => addr, - Err(e) => { - error!("Cannot parse SERVE_AT: {}", e); - std::process::exit(1); - } - }; - - // This thing handles redirects automatically but is type-incompatible with hyper::Client - // Bonus: less generics to be aware of, this thing hides its complexity - let http: reqwest::Client = { - #[allow(unused_mut)] - let mut builder = reqwest::Client::builder() - .user_agent(concat!( - env!("CARGO_PKG_NAME"), - "/", - env!("CARGO_PKG_VERSION") - )); - // TODO: add a root certificate if there's an environment variable pointing at it - //builder = builder.add_root_certificate(reqwest::Certificate::from_pem(todo!())); - - builder.build().unwrap() - }; - - if backend_uri.starts_with("redis") { - 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); - match kittybox::database::FileStorage::new(path).await { - Ok(db) => db, - Err(err) => { - error!("Error creating database: {:?}", err); - std::process::exit(1); - } - } - }; - - let endpoints = kittybox::frontend::IndiewebEndpoints { - authorization_endpoint: authorization_endpoint.to_string(), - token_endpoint: token_endpoint.to_string(), - webmention: None, - microsub: None, - }; - - 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() - .and(kittybox::micropub::micropub( - database.clone(), - token_endpoint.to_string(), - http.clone() - )) - .or(warp::get() - .and(warp::path("client")) - .and(warp::path::end()) - .map(|| warp::reply::html(kittybox::MICROPUB_CLIENT)))); - - 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!"))); - - // 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(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() - ])) - ; - - let svc = warp::service(app); - - 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() - }; - tcp_listener.set_nonblocking(true).unwrap(); - - info!("Listening on {}", tcp_listener.local_addr().unwrap()); - let server = hyper::server::Server::from_tcp(tcp_listener) - .unwrap() - .tcp_keepalive(Some(Duration::from_secs(30 * 60))) - .serve(hyper::service::make_service_fn(move |_| { - let service = svc.clone(); - async move { - Ok::<_, Infallible>(service) - } - })) - .with_graceful_shutdown(async move { - // Defer to C-c handler whenever we're not on Unix - // TODO consider using a diverging future here - #[cfg(not(unix))] - return tokio::signal::ctrl_c().await.unwrap(); - #[cfg(unix)] - { - use tokio::signal::unix::{signal, SignalKind}; - - signal(SignalKind::terminate()) - .unwrap() - .recv() - .await - .unwrap() - } - }); - - if let Err(err) = server.await { - error!("Error serving requests: {}", err); - std::process::exit(1); - } - } else { - println!("Unknown backend, not starting."); - std::process::exit(1); - } -} -- cgit 1.4.1