rust 53 lines · 8 steps

Logging request bodies in Axum middleware

An Axum middleware that buffers the entire request body, logs it, then rebuilds the request so downstream handlers still receive it.

Explained by highlit
1use axum::{
2 body::{Body, Bytes},
3 extract::Request,
4 http::StatusCode,
5 middleware::Next,
6 response::{IntoResponse, Response},
7};
8use http_body_util::BodyExt;
9 
10pub async fn log_request_body(request: Request, next: Next) -> Result<Response, Response> {
11 let (parts, body) = request.into_parts();
12 
13 let bytes = match body.collect().await {
14 Ok(collected) => collected.to_bytes(),
15 Err(err) => {
16 return Err((
17 StatusCode::BAD_REQUEST,
18 format!("failed to read request body: {err}"),
19 )
20 .into_response());
21 }
22 };
23 
24 log_payload(&parts.method, &parts.uri, &bytes);
25 
26 let request = Request::from_parts(parts, Body::from(bytes));
27 Ok(next.run(request).await)
28}
29 
30fn log_payload(method: &axum::http::Method, uri: &axum::http::Uri, bytes: &Bytes) {
31 const MAX_LOGGED: usize = 4096;
32 
33 if bytes.is_empty() {
34 tracing::info!(%method, %uri, "request with empty body");
35 return;
36 }
37 
38 match std::str::from_utf8(bytes) {
39 Ok(text) => {
40 let truncated = text.len() > MAX_LOGGED;
41 let body = &text[..text.len().min(MAX_LOGGED)];
42 tracing::info!(%method, %uri, truncated, body, "request body");
43 }
44 Err(_) => {
45 tracing::info!(
46 %method,
47 %uri,
48 bytes = bytes.len(),
49 "request body (binary, not logged)"
50 );
51 }
52 }
53}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Reading a streaming body is destructive, so you must reassemble the request before passing it on.
  2. 2Buffering the whole body into memory trades streaming efficiency for the ability to inspect it.
  3. 3Guarding logged output with a size cap and UTF-8 check keeps logs safe from huge or binary payloads.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Logging request bodies in Axum middleware — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code