Something went wrong. Try again.
Web frontend and supporting services for lance.blue
Something went wrong. Try again.
4.2 kB · 142 lines
Rust
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143mod atproto;mod camo;mod card;mod config;mod db;mod flare;mod matches;mod png_util;mod proxy;mod routes;mod session;mod share;mod unfurl;mod units;
use std::sync::Arc;
use axum::serve::{Listener, ListenerExt};
use crate::config::Config;use crate::routes::AppState;
#[tokio::main]async fn main() { // Logging discipline: manifest URLs, tokens and authorization codes never // appear in log output at any level — log that a thing failed, not the // values involved. tracing_subscriber::fmt() .with_env_filter( tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| "info".into()), ) .init();
tracing::info!( build = %std::env::var("BUILD_REF").unwrap_or_else(|_| "unknown".into()), "headquarters-api starting" );
let config = match Config::from_env() { Ok(config) => config, Err(e) => { tracing::error!("configuration: {e}"); std::process::exit(1); } };
let db = match db::Db::open(&config.db_path) { Ok(db) => db, Err(e) => { tracing::error!("database: {e}"); std::process::exit(1); } };
let atproto = match atproto::Atproto::new(&config, db.clone()) { Ok(atproto) => atproto, Err(e) => { tracing::error!("atproto: {e}"); std::process::exit(1); } };
tracing::info!( "oauth client: {}", if atproto.is_confidential() { "confidential" } else { "loopback (development)" } );
let matches = matches::Matches::new(&config, db.clone()) .await .map(Arc::new); tracing::info!( "match launching: {}", if matches.is_some() { "configured" } else { "not configured" } );
let lobbies = Arc::new(matches::lobby::Lobbies::new(db.clone()));
// Fetched here rather than on the first report, so a deployment says at // startup whether its pages will draw real machines or silhouettes. let units = units::load(config.unit_index_url.as_deref(), &config.web_origin).await;
let state = AppState { atproto: Arc::new(atproto), lobbies, db, signer: Arc::new(session::SessionSigner::new( config.session_secret.clone(), config.public_url.is_some(), config.cookie_domain.clone(), )), web_origin: config.web_origin.clone(), share_origin: config.share_origin.clone(), matches, build_ref: config.build_ref.clone(), arena_version: config.arena_version.clone(), flare_space: config.flare_space.clone(), units, };
let listener = tokio::net::TcpListener::bind(config.bind_addr) .await .unwrap_or_else(|e| panic!("cannot bind {}: {e}", config.bind_addr)) .tap_io(|stream| { if let Err(e) = stream.set_nodelay(true) { tracing::debug!("set_nodelay failed: {e}"); } }); // The bound address, not the configured one: BIND_ADDR=127.0.0.1:0 asks // the OS for whichever port is free, which is what scripts/dev-instance.sh // relies on this line to report - logging config.bind_addr back would // always print :0 and never say which port actually opened. let bound = listener .local_addr() .map(|a| a.to_string()) .unwrap_or_else(|_| config.bind_addr.to_string()); tracing::info!("listening on {bound}");
axum::serve(listener, routes::app(state)) .with_graceful_shutdown(shutdown_signal()) .await .expect("server error");}
/// Resolves on SIGINT or SIGTERM, so the container stops promptly instead of/// waiting out docker's kill timeout.async fn shutdown_signal() { let mut sigterm = tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate()) .expect("cannot install SIGTERM handler"); tokio::select! { _ = tokio::signal::ctrl_c() => {} _ = sigterm.recv() => {} } tracing::info!("shutting down");}