contact-form/src/main.rs
2023-02-26 17:02:09 +01:00

83 lines
2 KiB
Rust

mod captcha_solutions;
mod config;
mod errors;
mod forms;
mod logging;
mod mailer;
mod routes;
mod states;
mod templates;
use anyhow::{Context, Result};
use axum::{
routing::{get, get_service, Router},
Server,
};
use std::{env, net::SocketAddr, path::PathBuf, process};
use tower_http::services::ServeDir;
use tracing::{error, info};
use crate::{config::Config, states::AppState};
const DATA_DIR_ENV_VAR: &str = "CF_DATA_DIR";
async fn init(logger_initialized: &mut bool) -> Result<()> {
let data_dir = PathBuf::from(
env::var(DATA_DIR_ENV_VAR)
.with_context(|| format!("Environment variable {DATA_DIR_ENV_VAR} missing!"))?,
);
let config = Config::build(&data_dir)?;
logging::init_logger(&data_dir, &config.utc_offset)?;
*logger_initialized = true;
// The path prefix of all routes.
let path_prefix = config.state_config.path_prefix.clone();
let socket_address = config
.socket_address
.parse::<SocketAddr>()
.context("Failed to parse the socket address: {e:?}")?;
let app_state = AppState::build(config).await?;
// The service for serving the static files.
let static_service = get_service(ServeDir::new("static"));
let routes = Router::new()
.route("/", get(routes::index).post(routes::submit))
.with_state(app_state)
.nest_service("/static", static_service);
let app = {
if path_prefix.is_empty() {
// No need to nest.
routes
} else {
Router::new().nest(&path_prefix, routes)
}
};
info!("Starting server");
Server::bind(&socket_address)
.serve(app.into_make_service())
.await?;
Ok(())
}
/// Single thread.
#[tokio::main(flavor = "current_thread")]
async fn main() {
let mut logger_initialized = false;
if let Err(e) = init(&mut logger_initialized).await {
if logger_initialized {
error!("{e:?}");
} else {
eprintln!("{e:?}");
}
process::exit(1);
};
}