use std::net::SocketAddr; use axum::http::HeaderMap; use crate::consts; pub fn get_ip_and_user_agent(headers: &HeaderMap, remote_address: SocketAddr) -> (String, String) { let ip = match headers.get(consts::REVERSE_PROXY_IP_HTTP_FIELD) { Some(v) => v.to_str().unwrap_or_default().to_string(), None => remote_address.to_string(), }; let user_agent = headers .get(axum::http::header::USER_AGENT) .map(|v| v.to_str().unwrap_or_default()) .unwrap_or_default() .to_string(); (ip, user_agent) } pub fn get_url_from_host(host: &str) -> String { let port: Option = 'p: { let split_port: Vec<&str> = host.split(':').collect(); if split_port.len() == 2 { if let Ok(p) = split_port[1].parse::() { break 'p Some(p); } } None }; format!( "http{}://{}", if port.is_some() && port.unwrap() != 443 { "" } else { "s" }, host ) } pub fn substitute(str: &str, pattern: &str, replacements: &[&str]) -> String { let mut result = String::with_capacity( (str.len() + replacements.iter().map(|s| s.len()).sum::()) .saturating_sub(pattern.len() * replacements.len()), ); let mut i = 0; for s in str.split(pattern) { result.push_str(s); if i < replacements.len() { result.push_str(replacements[i]); } i += 1; } if i == 1 { return str.to_string(); } result } #[cfg(test)] mod tests { use super::*; #[test] fn test_substitute() { assert_eq!(substitute("", "", &[]), ""); assert_eq!(substitute("", "", &[""]), ""); assert_eq!(substitute("", "{}", &["a"]), ""); assert_eq!(substitute("a", "{}", &["b"]), "a"); assert_eq!(substitute("a{}", "{}", &["b"]), "ab"); assert_eq!(substitute("{}c", "{}", &["b"]), "bc"); assert_eq!(substitute("a{}c", "{}", &["b"]), "abc"); assert_eq!(substitute("{}b{}", "{}", &["a", "c"]), "abc"); assert_eq!(substitute("{}{}{}", "{}", &["a", "bc", "def"]), "abcdef"); assert_eq!(substitute("{}{}{}", "{}", &["a"]), "a"); } }