rustic_server/
log.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use axum::{
    body::{Body, Bytes},
    extract::Request,
    middleware::Next,
    response::{IntoResponse, Response},
};
use http_body_util::BodyExt;

use crate::error::ApiErrorKind;

// Add the `#[debug_middleware]` attribute to the function to make debugging easier.
// use axum_macros::debug_middleware;
//
// #[debug_middleware]
/// Router middleware function to print additional information on the request and response.
pub async fn print_request_response(
    req: Request,
    next: Next,
) -> Result<impl IntoResponse, ApiErrorKind> {
    let (parts, body) = req.into_parts();
    let uuid = uuid::Uuid::new_v4();

    tracing::debug!(
        id = %uuid,
        method = %parts.method,
        uri = %parts.uri,
        "[REQUEST]",
    );

    tracing::debug!(id = %uuid, headers = ?parts.headers, "[HEADERS]");

    let bytes = buffer_and_print(&uuid, body).await?;

    let req = Request::from_parts(parts, Body::from(bytes));

    let res = next.run(req).await;
    let (parts, body) = res.into_parts();

    tracing::debug!(
        id = %uuid,
        headers = ?parts.headers,
        status = %parts.status,
        "[RESPONSE]",
    );

    let bytes = buffer_and_print(&uuid, body).await?;
    let res = Response::from_parts(parts, Body::from(bytes));

    Ok(res)
}

async fn buffer_and_print<B>(uuid: &uuid::Uuid, body: B) -> Result<Bytes, ApiErrorKind>
where
    B: axum::body::HttpBody<Data = Bytes> + Send,
    B::Error: std::fmt::Display,
{
    let bytes = match body.collect().await {
        Ok(collected) => collected.to_bytes(),
        Err(err) => {
            return Err(ApiErrorKind::BadRequest(format!(
                "failed to read body: {err}"
            )));
        }
    };

    if let Ok(body) = std::str::from_utf8(&bytes) {
        tracing::debug!(id = %uuid, body = %body, "[BODY]");
    }

    Ok(bytes)
}