use axum::{extract::Request, http::HeaderValue, middleware::Next, response::Response};
use uuid::Uuid;
pub const REQUEST_ID_HEADER: &str = "x-request-id";
#[derive(Debug, Clone, Copy)]
pub struct RequestId(pub Uuid);
impl RequestId {
pub fn new() -> Self {
Self(Uuid::new_v4())
}
pub fn as_uuid(&self) -> Uuid {
self.0
}
pub fn as_str(&self) -> String {
self.0.to_string()
}
}
impl Default for RequestId {
fn default() -> Self {
Self::new()
}
}
impl std::fmt::Display for RequestId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
pub async fn request_id_middleware(mut request: Request, next: Next) -> Response {
let request_id = RequestId::new();
tracing::debug!(
request_id = %request_id,
method = %request.method(),
uri = %request.uri(),
"Incoming request"
);
request.extensions_mut().insert(request_id);
let mut response = next.run(request).await;
if let Ok(header_value) = HeaderValue::from_str(&request_id.to_string()) {
response
.headers_mut()
.insert(REQUEST_ID_HEADER, header_value);
}
response
}