use std::time::Duration;
use reqwest::header::{HeaderMap, HeaderValue};
use reqwest::Client;
pub const BROWSER_UA: &str = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36";
pub fn browser_headers() -> HeaderMap {
let mut headers = HeaderMap::new();
let h = |s: &str| HeaderValue::from_str(s).expect("valid header value");
headers.insert("accept", h("text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8"));
headers.insert("accept-language", h("en-US,en;q=0.9,de;q=0.8"));
headers.insert("accept-encoding", h("gzip"));
headers.insert("cache-control", h("no-cache"));
headers.insert("sec-fetch-dest", h("document"));
headers.insert("sec-fetch-mode", h("navigate"));
headers.insert("sec-fetch-site", h("none"));
headers.insert("sec-fetch-user", h("?1"));
headers.insert("upgrade-insecure-requests", h("1"));
headers
}
pub fn build_browser_client(timeout_secs: u64) -> reqwest::Result<Client> {
Client::builder()
.default_headers(browser_headers())
.user_agent(BROWSER_UA)
.redirect(reqwest::redirect::Policy::limited(10))
.timeout(Duration::from_secs(timeout_secs))
.gzip(true)
.build()
}
pub fn truncate_url(s: &str, max_len: usize) -> String {
if s.len() <= max_len {
return s.to_string();
}
let target = max_len.saturating_sub(3);
let boundary = s
.char_indices()
.take_while(|(i, _)| *i <= target)
.last()
.map(|(i, _)| i)
.unwrap_or(0);
format!("{}...", &s[..boundary])
}
pub fn truncate_ellipsis(s: &str, max: usize) -> String {
if s.len() <= max {
return s.to_string();
}
let boundary = s
.char_indices()
.take_while(|(i, _)| *i <= max.saturating_sub(3))
.last()
.map(|(i, _)| i)
.unwrap_or(0);
format!("{}…", &s[..boundary])
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_truncate_short_url() {
assert_eq!(
truncate_url("https://example.com", 30),
"https://example.com"
);
}
#[test]
fn test_truncate_long_url() {
let url = "https://example.com/very/long/path/that/exceeds/limit";
let result = truncate_url(url, 30);
assert!(result.len() <= 30);
assert!(result.ends_with("..."));
}
#[test]
fn test_truncate_ellipsis_long_string() {
let long = "a".repeat(200);
let result = truncate_ellipsis(&long, 120);
assert!(result.len() <= 120);
assert!(result.ends_with('…'));
}
#[test]
fn test_browser_headers_only_advertise_supported_encoding() {
let headers = browser_headers();
assert_eq!(headers["accept-encoding"], "gzip");
}
}