1pub fn init_logger() {}
6
7fn sensitive_header_value(
8 name: &reqwest::header::HeaderName,
9 value: &reqwest::header::HeaderValue,
10) -> String {
11 let name = name.as_str();
12 if name.eq_ignore_ascii_case("authorization") {
13 return "Bearer ***REDACTED***".to_string();
14 }
15 if name.eq_ignore_ascii_case("sb-access-token")
16 || name.eq_ignore_ascii_case("session-key")
17 || name.eq_ignore_ascii_case("x-session-key")
18 {
19 return "***REDACTED***".to_string();
20 }
21 if name.eq_ignore_ascii_case("x-session-id")
22 || name.eq_ignore_ascii_case("x-device-id")
23 || name.eq_ignore_ascii_case("x-install-id")
24 {
25 return format!(
26 "***{}",
27 &value
28 .to_str()
29 .unwrap_or("")
30 .chars()
31 .rev()
32 .take(4)
33 .collect::<String>()
34 .chars()
35 .rev()
36 .collect::<String>()
37 );
38 }
39 value.to_str().unwrap_or("").to_string()
40}
41
42pub fn format_headers(headers: &reqwest::header::HeaderMap) -> String {
44 let mut output = String::new();
45 for (name, value) in headers.iter() {
46 let value_str = sensitive_header_value(name, value);
47 output.push_str(&format!(" {}: {}\n", name.as_str(), value_str));
48 }
49 output
50}
51
52pub fn format_ws_headers(headers: &[(impl AsRef<str>, impl AsRef<str>)]) -> String {
54 let mut output = String::new();
55 for (name, value) in headers.iter() {
56 let n = name.as_ref();
57 let v = value.as_ref();
58 let value_str = if n.eq_ignore_ascii_case("SENDBIRD-WS-AUTH")
59 || n.eq_ignore_ascii_case("SENDBIRD-WS-TOKEN")
60 || n.eq_ignore_ascii_case("sb-access-token")
61 || n.eq_ignore_ascii_case("session-key")
62 || n.eq_ignore_ascii_case("x-session-key")
63 {
64 "***REDACTED***".to_string()
65 } else if n.eq_ignore_ascii_case("Cookie") {
66 "***".to_string()
67 } else if n.eq_ignore_ascii_case("x-session-id")
68 || n.eq_ignore_ascii_case("x-device-id")
69 || n.eq_ignore_ascii_case("x-install-id")
70 {
71 format!(
72 "***{}",
73 v.chars()
74 .rev()
75 .take(4)
76 .collect::<String>()
77 .chars()
78 .rev()
79 .collect::<String>()
80 )
81 } else {
82 v.to_string()
83 };
84 output.push_str(&format!(" {}: {}\n", n, value_str));
85 }
86 output
87}
88
89pub fn format_json(json: &serde_json::Value) -> String {
91 serde_json::to_string_pretty(json).unwrap_or_else(|_| "Invalid JSON".to_string())
92}
93
94pub fn log_request(
96 method: &str,
97 url: &str,
98 headers: &reqwest::header::HeaderMap,
99 body: Option<&serde_json::Value>,
100) {
101 log::info!("━━━━━━━━━━ HTTP REQUEST ━━━━━━━━━━");
102 log::info!("{} {}", method, url);
103 log::debug!("Headers:");
104 log::debug!("{}", format_headers(headers));
105
106 if let Some(body) = body {
107 log::debug!("Body:");
108 log::debug!("{}", format_json(body));
109 }
110 log::info!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
111}
112
113pub fn log_response(
115 status: reqwest::StatusCode,
116 headers: &reqwest::header::HeaderMap,
117 body: Option<&serde_json::Value>,
118) {
119 log::info!("━━━━━━━━━━ HTTP RESPONSE ━━━━━━━━━━");
120 log::info!("Status: {}", status);
121 log::debug!("Headers:");
122 for (name, value) in headers.iter() {
124 let value_str = sensitive_header_value(name, value);
125 log::debug!(" {}: {}", name.as_str(), value_str);
126 }
127
128 if let Some(body) = body {
129 log::debug!("Body:");
130 let formatted = format_json(body);
131 log::debug!("{}", formatted);
133 }
134 log::info!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
135}