Skip to main content

relay_core_lib/proxy/
body_codec.rs

1use data_encoding::BASE64;
2
3/// Helper to process body bytes into BodyData content and encoding
4pub fn process_body(bytes: &[u8], headers: &[(String, String)]) -> (String, String) {
5    // 1. Check content-type header
6    let content_type = headers
7        .iter()
8        .find(|(k, _)| k.eq_ignore_ascii_case("content-type"))
9        .map(|(_, v)| v.to_lowercase())
10        .unwrap_or_default();
11
12    // Heuristic 1: If explicit charset is present, treat as text
13    if content_type.contains("charset=utf-8")
14        || content_type.contains("charset=us-ascii")
15        || content_type.contains("text/")
16        || content_type.contains("application/json")
17        || content_type.contains("application/xml")
18        || content_type.contains("application/javascript")
19    {
20        // Try UTF-8 decode first to be safe, if fails, fallback to base64
21        match std::str::from_utf8(bytes) {
22            Ok(s) => return ("utf-8".to_string(), s.to_string()),
23            Err(_) => return ("base64".to_string(), BASE64.encode(bytes)),
24        }
25    }
26
27    // Heuristic 2: Known binary types
28    if content_type.starts_with("image/")
29        || content_type.starts_with("audio/")
30        || content_type.starts_with("video/")
31        || content_type.contains("application/octet-stream")
32        || content_type.contains("application/pdf")
33        || content_type.contains("application/zip")
34    {
35        return ("base64".to_string(), BASE64.encode(bytes));
36    }
37
38    // Heuristic 3: Try UTF-8 decode as fallback
39    match std::str::from_utf8(bytes) {
40        Ok(s) => ("utf-8".to_string(), s.to_string()),
41        Err(_) => ("base64".to_string(), BASE64.encode(bytes)),
42    }
43}