use axum::{ body::Body, extract::{Request, State}, middleware::Next, response::Response, }; use chrono::Local; use std::time::Instant; use crate::state::SharedState; use colored::*; // Note: Axum body might need to be imported differently depending on version // but since the original used axum::body::Body, I'll stick to that or similar. // Actually, let's use axum::body::Body. pub async fn logging_middleware( State(_state): State, req: Request, next: Next, ) -> Response { let start_time = Local::now(); let start_instant = Instant::now(); // Load config live for masking settings let config = crate::config::Config::load(); let method = req.method().clone(); let path = req.uri().path().to_string(); println!("{}", format!("---- REQUEST START {} ----", start_time.format("%Y-%m-%d %H:%M:%S")).blue().bold()); println!("{}: {}", "Method".bright_black(), method); println!("{}: {}", "Path".bright_black(), path); println!("{}:", "Headers".bright_black()); for (name, value) in req.headers() { let name_str = name.as_str(); let should_mask = config.masking.enabled && config.masking.headers.iter().any(|h| h.eq_ignore_ascii_case(name_str)); if should_mask { println!(" {}: {}", name_str.bright_black(), "***".yellow()); } else { println!(" {}: {:?}", name_str.bright_black(), value); } } let response = next.run(req).await; let end_time = Local::now(); let duration = start_instant.elapsed(); let status = response.status(); let status_colored = if status.is_success() { status.to_string().green() } else if status.is_server_error() { status.to_string().red() } else if status.is_client_error() { status.to_string().yellow() } else { status.to_string().cyan() }; println!("{}: {}", "Status".bright_black(), status_colored.bold()); println!("{}", format!("--- REQUEST END {} - {:?} ---------", end_time.format("%H:%M:%S"), duration).blue().bold()); println!(); response }