use crate::{
HeadersDebug, LatencyDisplay, WrappedRedactedHashingAlg, X_FORWARDED_FOR, X_FORWARDED_HOST,
X_FORWARDED_PROTO, X_VIA, get_host, get_http_version_str, get_mapped_ip_for_addr,
};
use axum::extract::{ConnectInfo, Request};
use axum::http::{HeaderMap, HeaderValue, header};
use std::net::SocketAddr;
use std::sync::Arc;
use std::time::Instant;
pub fn log_response(
status: u16,
log_headers: bool,
redacted_hash: &Arc<Option<WrappedRedactedHashingAlg>>,
start: Instant,
headers: &HeaderMap,
) {
let hd = log_headers.then_some(HeadersDebug(headers, redacted_hash.clone()));
#[cfg(tracing_unstable)]
let headers = log_headers.then_some(tracing::field::valuable(&hd));
#[cfg(not(tracing_unstable))]
let headers = log_headers.then_some(tracing::field::debug(&hd));
let latency = LatencyDisplay(start.elapsed().as_nanos() as f64);
if status >= 500 {
tracing::error!(status, headers, %latency, "res");
} else if status >= 400 {
tracing::warn!(status, headers, %latency, "res");
} else {
tracing::info!(status, headers, %latency, "res");
}
}
pub fn get_request_headers_for_forward(
req: &Request,
forwarded_by: &str,
forwarded_proto: &str,
via_domain: &str,
) -> HeaderMap {
let mut headers = req.headers().clone();
let req_version = get_http_version_str(req.version());
let via = if let Some(src_via) = headers.get(header::VIA)
&& let Ok(src_via) = src_via.to_str()
{
format!("{src_via}, {req_version} {via_domain} (ordinaryd)")
} else {
format!("{req_version} {via_domain} (ordinaryd)")
};
if let Ok(via) = HeaderValue::from_str(&via) {
headers.insert(header::VIA, via);
}
let connect_info = req.extensions().get::<ConnectInfo<SocketAddr>>();
let mut forwarded = if let Some(src_forwarded) = headers.get(header::FORWARDED)
&& let Ok(src_forwarded) = src_forwarded.to_str()
{
format!("{src_forwarded}, by={forwarded_by}")
} else {
format!("by={forwarded_by}")
};
if let Some(addr) = connect_info {
let ip = get_mapped_ip_for_addr(&addr.0);
let ip_str = ip.to_string();
if ip.is_ipv6() {
forwarded = format!("{forwarded};for=\"[{ip_str}]\"");
} else {
forwarded = format!("{forwarded};for={ip_str}");
}
let forwarded_for = if let Some(src_forwarded_for) = headers.get("x-forwarded-for")
&& let Ok(src_forwarded_for) = src_forwarded_for.to_str()
{
format!("{src_forwarded_for}, {ip_str}")
} else {
ip_str
};
if let Ok(forwarded_for) = HeaderValue::from_str(&forwarded_for) {
headers.insert(X_FORWARDED_FOR, forwarded_for);
}
}
if let Some(host) = get_host(req.headers(), req.uri()) {
forwarded = format!("{forwarded};host={host}");
if let Ok(forwarded_host) = HeaderValue::from_str(host.as_str()) {
headers.insert(X_FORWARDED_HOST, forwarded_host);
}
}
forwarded = format!("{forwarded};proto={forwarded_proto}");
if let Ok(forwarded_proto) = HeaderValue::from_str(forwarded_proto) {
headers.insert(X_FORWARDED_PROTO, forwarded_proto);
}
if let Ok(forwarded) = HeaderValue::from_str(&forwarded) {
headers.insert(header::FORWARDED, forwarded);
}
headers.remove(X_VIA);
headers
}