aboutsummaryrefslogtreecommitdiffstats
path: root/src/api/auth.rs
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-09 04:09:09 +0000
committertv <tv@krebsco.de>2026-11-09 05:13:32 +0100
commitd30ac9c7aede4cbc6463ec1ee80b650b7bf9e9c7 (patch)
tree6b233e7540210cf948e69f3853dd5f9bc4d5530a /src/api/auth.rs
parent19535a851b2a528bcd19f44b73a2d90b46adaa5e (diff)
api: a log line per HTTP request
Requests weren't logged at all, short of what a handler logs itself. Now a middleware, outermost on the API (and on a relay-only node's), logs a line per request as web servers do: method and path (with the query), status, the milliseconds until the answer began (a stream goes on after), where it came from (the address, or `unix`), and the user (`-` where none was authenticated). The user comes back on the response: `basic_auth` puts it there, for a token as for a password or a trusted proxy's header. At debug, under the target `http` (`RUST_LOG=info,http=debug`, or `PUT /admin/log`): an open dashboard alone would fill the log at info. With the target off, the request passes untouched.
Diffstat (limited to 'src/api/auth.rs')
-rw-r--r--src/api/auth.rs19
1 files changed, 14 insertions, 5 deletions
diff --git a/src/api/auth.rs b/src/api/auth.rs
index ac70b82..f4806ca 100644
--- a/src/api/auth.rs
+++ b/src/api/auth.rs
@@ -211,7 +211,8 @@ fn parse_basic(headers: &HeaderMap) -> Option<(String, String)> {
}
/// The user a request authenticated as (a request extension, set by [`basic_auth`], or
-/// by `login::bearer` for a token).
+/// by `login::bearer` for a token; on the response too, for the request log,
+/// `request_log`).
#[derive(Clone, Debug)]
pub(crate) struct AuthenticatedUser(pub(crate) String);
@@ -293,8 +294,8 @@ pub(crate) async fn basic_auth(
next: axum::middleware::Next,
) -> Response {
// A token, taken already (`login::bearer`).
- if request.extensions().get::<AuthenticatedUser>().is_some() {
- return next.run(request).await;
+ if let Some(user) = request.extensions().get::<AuthenticatedUser>().cloned() {
+ return with_user(next.run(request).await, user);
}
let from = request
.extensions()
@@ -343,9 +344,17 @@ pub(crate) async fn basic_auth(
};
};
- request.extensions_mut().insert(AuthenticatedUser(user));
+ request
+ .extensions_mut()
+ .insert(AuthenticatedUser(user.clone()));
request.extensions_mut().insert(via);
- next.run(request).await
+ with_user(next.run(request).await, AuthenticatedUser(user))
+}
+
+/// `response`, naming the user it answered (`request_log`).
+fn with_user(mut response: Response, user: AuthenticatedUser) -> Response {
+ response.extensions_mut().insert(user);
+ response
}
#[cfg(test)]