1use axum::{
2 body::Body,
3 extract::{ConnectInfo, FromRequestParts},
4 http::{Method, Request, StatusCode},
5 middleware::Next,
6 response::Response,
7};
8use axum_extra::extract::TypedHeader;
9use headers::{Origin, UserAgent};
10use std::net::SocketAddr;
11use tracing::info;
12use crate::auth::claims::AuthUser;
13
14pub async fn log_request(
39 ConnectInfo(addr): ConnectInfo<SocketAddr>,
40 req: Request<Body>,
41 next: Next,
42) -> Result<Response, StatusCode> {
43 let (mut parts, body) = req.into_parts();
44
45 if parts.method == Method::OPTIONS {
47 let req = Request::from_parts(parts, body);
48 return Ok(next.run(req).await);
49 }
50
51 let user_id = AuthUser::from_request_parts(&mut parts, &())
53 .await
54 .ok()
55 .map(|AuthUser(c)| c.sub);
56
57 let origin = TypedHeader::<Origin>::from_request_parts(&mut parts, &())
59 .await
60 .ok()
61 .map(|TypedHeader(o)| o.to_string());
62
63 let user_agent = TypedHeader::<UserAgent>::from_request_parts(&mut parts, &())
64 .await
65 .ok()
66 .map(|TypedHeader(ua)| ua.to_string());
67
68 info!(
70 method = ?parts.method,
71 path = %parts.uri.path(),
72 ip = %addr.ip(),
73 user = user_id.unwrap_or(0),
74 origin = origin.unwrap_or_else(|| "unknown".into()),
75 user_agent = user_agent.unwrap_or_else(|| "unknown".into()),
76 "Incoming request"
77 );
78
79 let req = Request::from_parts(parts, body);
80 Ok(next.run(req).await)
81}