mod admin; mod healthcheck; use std::sync::mpsc; use std::time::Duration; use crate::AppState; use axum::extract::Request; use axum::routing::get; use axum::{Router, body::Body}; use http::{HeaderName, HeaderValue}; use tower::ServiceBuilder; use tower_http::request_id::{MakeRequestId, RequestId, SetRequestIdLayer}; use tower_http::timeout::TimeoutLayer; use tower_http::trace::TraceLayer; use tracing::Level; use uuid::Uuid; #[derive(Clone)] struct RequestIdLayer; impl MakeRequestId for RequestIdLayer { fn make_request_id(&mut self, _: &http::Request) -> Option { let id = Uuid::now_v7().to_string(); Some(RequestId::new(id.parse().unwrap())) } } pub fn app(state: &AppState) -> (Router, mpsc::Receiver) { let (tx, rx) = mpsc::channel(); ( Router::new() .with_state(state.clone()) .route("/healthcheck", get(healthcheck::healthcheck)) .route("/forever", get(std::future::pending::<()>)) .nest("/admin", admin::router(tx, state)) .layer( ServiceBuilder::new() .layer(SetRequestIdLayer::new( HeaderName::from_static("x-request-id"), RequestIdLayer, )) .layer( TraceLayer::new_for_http().make_span_with(|req: &Request| { let default = HeaderValue::from_static(""); let req_id = req.headers().get("x-request-id").unwrap_or(&default); tracing::span!( Level::DEBUG, "request", req_id = req_id.to_str().unwrap(), method = format!("{}", req.method()), uri = format!("{}", req.uri()), ) }), ) .layer(TimeoutLayer::new(Duration::from_secs(10))), ), rx, ) }