use std::net::SocketAddr; use axum::{extract::MatchedPath, http::Request, routing::get, Router}; use tokio_util::sync::CancellationToken; use tower_http::trace::TraceLayer; use crate::state::SharedState; pub struct Api { state: SharedState, host: SocketAddr, } impl Api { pub fn new(state: impl Into, host: impl Into) -> Self { Self { state: state.into(), host: host.into(), } } pub async fn serve(&self) -> anyhow::Result<()> { let app = Router::new() .route("/", get(root)) .with_state(self.state.clone()) .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); tracing::info_span!( "http_request", method = ?request.method(), matched_path, some_other_field = tracing::field::Empty, ) }), // ... ); tracing::info!("listening on {}", self.host); let listener = tokio::net::TcpListener::bind(&self.host).await.unwrap(); axum::serve(listener, app.into_make_service()) .await .unwrap(); Ok(()) } } async fn root() -> &'static str { "Hello, churn!" } #[async_trait::async_trait] impl notmad::Component for Api { async fn run(&self, _cancellation_token: CancellationToken) -> Result<(), notmad::MadError> { self.serve().await.map_err(notmad::MadError::Inner)?; Ok(()) } }