Skip to main content

api_gateway/middleware/
request_id.rs

1use axum::http::{HeaderName, Request};
2use axum::{body::Body, middleware::Next, response::Response};
3use tower_http::request_id::{MakeRequestId, RequestId};
4
5#[derive(Clone, Debug)]
6pub struct XRequestId(pub String);
7
8#[must_use]
9pub fn header() -> HeaderName {
10    HeaderName::from_static("x-request-id")
11}
12
13#[derive(Clone, Default)]
14pub struct MakeReqId;
15
16impl MakeRequestId for MakeReqId {
17    fn make_request_id<B>(&mut self, _req: &Request<B>) -> Option<RequestId> {
18        // Generate a unique request ID using nanoid
19        let id = nanoid::nanoid!();
20        Some(RequestId::new(id.parse().ok()?))
21    }
22}
23
24/// Middleware that stores `request_id` in Request.extensions and records it in the current span
25pub async fn push_req_id_to_extensions(mut req: Request<Body>, next: Next) -> Response {
26    let hdr = header();
27    if let Some(rid) = req
28        .headers()
29        .get(&hdr)
30        .and_then(|v| v.to_str().ok())
31        .map(ToString::to_string)
32    {
33        // Save for business logic usage
34        req.extensions_mut().insert(XRequestId(rid.clone()));
35        // Record into the current http span (created by TraceLayer)
36        tracing::Span::current().record("request_id", rid.as_str());
37    }
38
39    next.run(req).await
40}