Skip to main content

fslite_server/
tracing_mw.rs

1use axum::extract::Request;
2use axum::http::HeaderValue;
3use axum::middleware::Next;
4use axum::response::Response;
5use tower_http::trace::TraceLayer;
6use uuid::Uuid;
7
8const REQUEST_ID_HEADER: &str = "x-request-id";
9
10/// Ensures every request carries an `x-request-id`, generating one when
11/// absent, and echoes it back on the response for client-side correlation.
12pub async fn request_id(mut request: Request, next: Next) -> Response {
13    let id = request
14        .headers()
15        .get(REQUEST_ID_HEADER)
16        .and_then(|value| value.to_str().ok())
17        .map(str::to_string)
18        .unwrap_or_else(|| Uuid::now_v7().to_string());
19
20    request.extensions_mut().insert(RequestId(id.clone()));
21
22    let mut response = next.run(request).await;
23    if let Ok(value) = HeaderValue::from_str(&id) {
24        response.headers_mut().insert(REQUEST_ID_HEADER, value);
25    }
26    response
27}
28
29/// The per-request correlation id, available to handlers via `Extension<RequestId>`.
30#[derive(Clone, Debug)]
31pub struct RequestId(pub String);
32
33/// A `tower-http` layer logging method, path, status, and latency per request.
34pub fn trace_layer()
35-> TraceLayer<tower_http::classify::SharedClassifier<tower_http::classify::ServerErrorsAsFailures>>
36{
37    TraceLayer::new_for_http()
38}