use axum::{extract::Request, routing::get, Router, ServiceExt}; use middleware::cache_control::cache_static; use posts::fs_post_repo::FsPostRepo; use std::{env, sync::Arc}; use tower::Layer; use tower_http::services::ServeDir; use tower_http::{ normalize_path::NormalizePathLayer, trace::{self, TraceLayer}, }; use tracing::{info, Level}; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; use tutors::fs_tutor_repo::FsTutorRepo; mod handlers; mod helpers; mod middleware; mod posts; mod tutors; mod views; #[tokio::main] async fn main() { let tracing_filter = EnvFilter::builder() .with_env_var("CT_LOG") .try_from_env() .unwrap_or("carpentertutoring=debug,tower_http=debug,axum::rejection=trace".into()); tracing_subscriber::registry() .with(tracing_filter) .with(tracing_subscriber::fmt::layer()) .init(); info!("loading state..."); let blog_dir = env::var("CT_POSTS").unwrap_or(String::from("/var/ct/posts")); let tutor_dir = env::var("CT_TEAM").unwrap_or(String::from("/var/ct/team")); let assets_dir = env::var("CT_ASSETS").unwrap_or(String::from("/var/ct/assets")); let posts = Arc::new(FsPostRepo::with_dir(blog_dir)); let tutors = Arc::new(FsTutorRepo::with_dir(tutor_dir.clone())); info!("initializing router..."); let app = Router::new() .route("/", get(handlers::index_handler)) .route("/posts", get(handlers::posts_handler)) .route("/posts/:post_id", get(handlers::post_handler)) .with_state(posts) .route("/policies", get(handlers::policies_handler)) .route("/brochure", get(handlers::brochure_handler)) .route("/about", get(handlers::about_handler)) .route("/k12", get(handlers::k12_handler)) .with_state(tutors) .nest_service("/assets", ServeDir::new(assets_dir)) .nest_service("/team", ServeDir::new(tutor_dir)) .fallback_service(ServeDir::new("static")) .layer(axum::middleware::from_fn(cache_static)) .layer( TraceLayer::new_for_http() .make_span_with(trace::DefaultMakeSpan::new().level(Level::INFO)) .on_response(trace::DefaultOnResponse::new().level(Level::INFO)), ); let app = NormalizePathLayer::trim_trailing_slash().layer(app); let addr = env::var("CT_BIND").unwrap_or("0.0.0.0:8000".into()); let listener = tokio::net::TcpListener::bind(addr).await.unwrap(); axum::serve(listener, ServiceExt::::into_make_service(app)) .await .unwrap(); }