use std::net::SocketAddr; use axum::{ extract::MatchedPath, http::{Method, Request}, }; use tokio::net::TcpListener; use tower::ServiceBuilder; use tower_http::{ cors::{Any, CorsLayer}, trace::TraceLayer, }; use tracing::info_span; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; use utoipa::OpenApi; use utoipa_axum::router::OpenApiRouter; use utoipa_swagger_ui::SwaggerUi; use crate::{docs::ApiDoc, models::states::AppState}; mod constants; mod controllers; mod docs; mod models; mod repositories; mod schema; mod services; #[tokio::main] async fn main() -> anyhow::Result<()> { tracing_subscriber::registry() .with( tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| { // axum logs rejections from built-in extractors with the `axum::rejection` // target, at `TRACE` level. `axum::rejection=trace` enables showing those events format!( "{}=debug,tower_http=debug,axum::rejection=trace", env!("CARGO_CRATE_NAME") ) .into() }), ) .with(tracing_subscriber::fmt::layer()) .init(); let cors = CorsLayer::new() .allow_methods([Method::GET, Method::POST]) .allow_origin(Any); let (router, api) = OpenApiRouter::with_openapi(ApiDoc::openapi()) .nest("/api", controllers::router()) .split_for_parts(); let trace_layer = TraceLayer::new_for_http().make_span_with(|request: &Request<_>| { // Log the matched route's path (with placeholders not filled in). // Use request.uri() or OriginalUri if you want the real path. let matched_path = request .extensions() .get::() .map(MatchedPath::as_str); info_span!( "http_request", method = ?request.method(), matched_path, some_other_field = tracing::field::Empty, ) }); let app = router .merge(SwaggerUi::new("/swagger-ui").url("/api-docs/openapi.json", api.clone())) .layer(trace_layer) .layer(ServiceBuilder::new().layer(cors)) .with_state(AppState::new().await?); let listener = TcpListener::bind(SocketAddr::from(([127, 0, 0, 1], 8080))).await?; axum::serve(listener, app).await?; Ok(()) }