datui_lib/cloud/
user_agent.rs1use std::sync::RwLock;
9
10pub const DEFAULT: &str = concat!(
12 "datui/",
13 env!("CARGO_PKG_VERSION"),
14 " (+https://github.com/derekwisong/datui)"
15);
16
17static CONFIGURED: RwLock<Option<String>> = RwLock::new(None);
20
21pub fn is_valid(value: &str) -> bool {
24 value.chars().all(|c| (' '..='~').contains(&c))
25}
26
27pub fn configure(setting: &str) {
29 let value = setting.trim();
30 *CONFIGURED.write().unwrap_or_else(|e| e.into_inner()) =
31 (!value.is_empty()).then(|| value.to_string());
32}
33
34pub fn get() -> String {
36 match CONFIGURED
37 .read()
38 .unwrap_or_else(|e| e.into_inner())
39 .as_deref()
40 {
41 Some(value) => value.to_string(),
42 None => DEFAULT.to_string(),
43 }
44}
45
46#[cfg(any(feature = "http", feature = "cloud"))]
48pub fn ureq_config() -> ureq::config::ConfigBuilder<ureq::typestate::AgentScope> {
49 ureq::Agent::config_builder().user_agent(get())
50}
51
52#[cfg(feature = "cloud")]
55pub const CLIENT_KEY: object_store::ClientConfigKey = object_store::ClientConfigKey::UserAgent;
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60
61 #[test]
62 fn the_default_names_datui_its_version_and_home_and_nothing_else() {
63 assert_eq!(
64 DEFAULT,
65 format!(
66 "datui/{} (+https://github.com/derekwisong/datui)",
67 env!("CARGO_PKG_VERSION")
68 )
69 );
70 assert!(is_valid(DEFAULT));
71 }
72
73 #[test]
74 fn control_characters_are_not_a_header() {
75 assert!(is_valid("my-tool/1.0 (+https://example.com)"));
76 assert!(!is_valid("a\r\nX-Injected: 1"));
77 assert!(!is_valid("café"));
78 }
79}