ordinary_utils/
headers.rs1use crate::tcp::Sni;
6use crate::{
7 HeadersDebug, LatencyDisplay, WrappedRedactedHashingAlg, X_FORWARDED_FOR, X_FORWARDED_HOST,
8 X_FORWARDED_PROTO, get_host_fwd, get_http_version_str, get_mapped_ip_for_addr,
9};
10use axum::extract::{ConnectInfo, Request};
11use axum::http::{HeaderMap, HeaderValue, header};
12use hyper::{Method, Version};
13use std::net::SocketAddr;
14use std::sync::Arc;
15use std::time::Instant;
16
17pub fn log_request(
18 log_headers: bool,
19 headers: &HeaderMap,
20 redacted_hash: &Arc<Option<WrappedRedactedHashingAlg>>,
21 method: &Method,
22) {
23 {
24 let hd = log_headers.then_some(HeadersDebug(headers, redacted_hash.clone()));
25
26 #[cfg(tracing_unstable)]
27 let headers = log_headers.then_some(tracing::field::valuable(&hd));
28 #[cfg(not(tracing_unstable))]
29 let headers = log_headers.then_some(tracing::field::debug(&hd));
30
31 tracing::info!(
32 %method,
33 headers,
34 "req"
35 );
36 }
37}
38
39pub fn log_response(
40 status: u16,
41 log_headers: bool,
42 redacted_hash: &Arc<Option<WrappedRedactedHashingAlg>>,
43 start: Instant,
44 headers: &HeaderMap,
45 version: Version,
46) {
47 let hd = log_headers.then_some(HeadersDebug(headers, redacted_hash.clone()));
48
49 #[cfg(tracing_unstable)]
50 let headers = log_headers.then_some(tracing::field::valuable(&hd));
51 #[cfg(not(tracing_unstable))]
52 let headers = log_headers.then_some(tracing::field::debug(&hd));
53
54 let latency = LatencyDisplay(start.elapsed().as_nanos() as f64);
55
56 if status >= 500 {
57 tracing::error!(version = ?version, status, headers, %latency, "res");
58 } else if status >= 400 {
59 tracing::warn!(version = ?version, status, headers, %latency, "res");
60 } else {
61 tracing::info!(version = ?version, status, headers, %latency, "res");
62 }
63}
64
65pub fn get_request_headers_for_forward(
66 req: &Request,
67 forwarded_by: &str,
68 forwarded_proto: &str,
69 via_domain: &str,
70) -> HeaderMap {
71 let mut headers = req.headers().clone();
72
73 let req_version = get_http_version_str(req.version());
74
75 let via = if let Some(src_via) = headers.get(header::VIA)
76 && let Ok(src_via) = src_via.to_str()
77 {
78 format!("{src_via}, {req_version} {via_domain} (ordinaryd)")
79 } else {
80 format!("{req_version} {via_domain} (ordinaryd)")
81 };
82
83 if let Ok(via) = HeaderValue::from_str(&via) {
84 headers.insert(header::VIA, via);
85 }
86
87 let connect_info = req.extensions().get::<ConnectInfo<SocketAddr>>();
88 let sni = req.extensions().get::<Sni>();
89
90 let mut forwarded = if let Some(src_forwarded) = headers.get(header::FORWARDED)
91 && let Ok(src_forwarded) = src_forwarded.to_str()
92 {
93 format!("{src_forwarded}, by={forwarded_by}")
94 } else {
95 format!("by={forwarded_by}")
96 };
97
98 if let Some(addr) = connect_info {
99 let ip = get_mapped_ip_for_addr(&addr.0);
100 let ip_str = ip.to_string();
101
102 if ip.is_ipv6() {
103 forwarded = format!("{forwarded};for=\"[{ip_str}]\"");
104 } else {
105 forwarded = format!("{forwarded};for={ip_str}");
106 }
107
108 let forwarded_for = if let Some(src_forwarded_for) = headers.get("x-forwarded-for")
109 && let Ok(src_forwarded_for) = src_forwarded_for.to_str()
110 {
111 format!("{src_forwarded_for}, {ip_str}")
112 } else {
113 ip_str
114 };
115
116 if let Ok(forwarded_for) = HeaderValue::from_str(&forwarded_for) {
117 headers.insert(X_FORWARDED_FOR, forwarded_for);
118 }
119 }
120
121 if let Some(host) = get_host_fwd(req.headers(), req.uri(), sni) {
122 forwarded = format!("{forwarded};host={host}");
123
124 if let Ok(forwarded_host) = HeaderValue::from_str(host.as_str()) {
125 headers.insert(X_FORWARDED_HOST, forwarded_host);
126 }
127 }
128
129 forwarded = format!("{forwarded};proto={forwarded_proto}");
130
131 if let Ok(forwarded_proto) = HeaderValue::from_str(forwarded_proto) {
132 headers.insert(X_FORWARDED_PROTO, forwarded_proto);
133 }
134
135 if let Ok(forwarded) = HeaderValue::from_str(&forwarded) {
136 headers.insert(header::FORWARDED, forwarded);
137 }
138
139 headers
140}