mod db; mod errors; mod logger; use sqlx::postgres::PgPool; use axum::{ http::{header, Request}, routing::get, Json, Router, }; use serde::Serialize; use std::time::Duration; use tower_http::sensitive_headers::SetSensitiveHeadersLayer; use tower_http::{classify::ServerErrorsFailureClass, trace::TraceLayer}; use tracing::Span; #[tokio::main] async fn main() { let app = create_app().await; let addr: String = std::env::var("ALLOWED_HOST").unwrap_or_else(|_| "localhost:3000".to_string()); tracing::info!("Listening on {}", addr); axum::Server::bind(&"127.0.0.1:3000".parse().unwrap()) .serve(app.into_make_service()) .await .unwrap(); } async fn create_app() -> Router { logger::setup(); let _ = db::setup().await; let pool = unsafe { match db::get_client() { Some(client) => client, None => panic!("Connection not established!"), } }; Router::new() .route("/", get(hej)) // Mark the `Authorization` request header as sensitive so it doesn't // show in logs. .layer(SetSensitiveHeadersLayer::new(std::iter::once( header::AUTHORIZATION, ))) .layer( TraceLayer::new_for_http() .on_request(|request: &Request<_>, _span: &Span| { tracing::info!("{} {}", request.method(), request.uri()); }) .on_failure( |error: ServerErrorsFailureClass, latency: Duration, _span: &Span| { tracing::error!("{} | {} s", error, latency.as_secs()); }, ), ) } // Example root which says hi async fn hej() -> Result, errors::AppError> { Ok(Json(Hej::new("hej verden".to_string()))) } #[derive(Debug, Serialize)] struct Hej { hello: String, } impl Hej { fn new(hello: String) -> Self { Self { hello } } }