use axum::{middleware, Extension, Router}; use std::net::SocketAddr; use tower_http::trace::TraceLayer; pub mod configuration; pub mod session_id; use configuration::{get_configuration, Settings}; mod errors; mod routes; use routes::routes; use sqlx::postgres::PgPoolOptions; pub async fn app(configuration: &Settings) -> Router { let format = tracing_subscriber::fmt::format() .with_level(false) // don't include levels in formatted output .with_thread_names(true) .json(); // include the name of the current thread tracing_subscriber::fmt().event_format(format).init(); let pool = PgPoolOptions::new() .max_connections(50) .connect(&configuration.database.url()) .await .expect("could not connect to database_url"); routes() .layer(Extension(pool)) .layer(TraceLayer::new_for_http()) .layer(middleware::from_fn(session_id::session_id)) } pub async fn run() { let configuration = get_configuration().unwrap(); let addr = SocketAddr::from(([127, 0, 0, 1], configuration.port)); let routes = app(&configuration).await; tracing::info!("listening on {}", addr); axum::Server::bind(&addr) .serve(routes.into_make_service()) .await .unwrap() } #[cfg(test)] mod tests { use super::*; use axum::{body::Body, http::Request}; use std::net::{SocketAddr, TcpListener}; #[tokio::test] async fn the_real_deal() { let configuration = get_configuration().unwrap(); let listener = TcpListener::bind("127.0.0.1:0".parse::().unwrap()).unwrap(); let addr = listener.local_addr().unwrap(); tokio::spawn(async move { axum::Server::from_tcp(listener) .unwrap() .serve(app(&configuration).await.into_make_service()) .await .unwrap(); }); let response = hyper::Client::new() .request( Request::builder() .uri(format!("http://{}/", addr)) .body(Body::empty()) .unwrap(), ) .await .unwrap(); let body = hyper::body::to_bytes(response.into_body()).await.unwrap(); assert_eq!(&body[..], b"Hello, World!\n"); } }