mod global; mod models; mod routes; use axum::http::{StatusCode, Uri}; use axum::response::IntoResponse; use axum::routing::{get, put}; use dotenvy::dotenv; use http::{HeaderName, Method}; use sqlx::SqlitePool; use tower::ServiceBuilder; use tower_http::cors::{Any, CorsLayer}; #[tokio::main] async fn main() { if let Err(e) = dotenv() { println!("WARN: did not read .env file: {}", e); } let database_url = std::env::var("DATABASE_URL").unwrap(); let db_pool = SqlitePool::connect(&database_url).await.unwrap(); let state = global::AppState { db_pool: db_pool.into(), }; let app = axum::Router::new() .fallback(handle404) .route("/", get(routes::tasks::home)) .nest_service("/assets", tower_http::services::ServeDir::new("assets")) .nest_service( "/favicon.ico", tower_http::services::ServeFile::new("assests/favicon.ico"), ) .route( "/tasks", get(routes::tasks::list).post(routes::tasks::create), ) .route( "/tasks/:task_id", put(routes::tasks::put).delete(routes::tasks::delete), ) .route("/tasks/:task_id/edit", get(routes::tasks::edit)) .layer( ServiceBuilder::new().layer( CorsLayer::new() .allow_headers([HeaderName::from_lowercase(b"content-type").unwrap()]) .allow_methods([Method::GET, Method::POST, Method::DELETE]) .allow_origin(Any), ), ) .with_state(state); let listener = tokio::net::TcpListener::bind("127.0.0.1:3000") .await .unwrap(); let server = axum::serve(listener, app); println!("Listening on http://127.0.0.1:3000"); server.await.unwrap(); } async fn handle404(uri: Uri) -> impl IntoResponse { (StatusCode::NOT_FOUND, format!("URI: {} Not Found", uri)) }