rws_proxy/traffic/
config.rs1use std::path::PathBuf;
4
5pub const RWS_CONFIG_TRAFFIC_ENABLED: &str = "RWS_CONFIG_TRAFFIC_ENABLED";
6pub const RWS_CONFIG_TRAFFIC_RETENTION_DAYS: &str = "RWS_CONFIG_TRAFFIC_RETENTION_DAYS";
7pub const RWS_CONFIG_TRAFFIC_PERSIST: &str = "RWS_CONFIG_TRAFFIC_PERSIST";
8pub const RWS_CONFIG_TRAFFIC_EXCLUDE: &str = "RWS_CONFIG_TRAFFIC_EXCLUDE";
9pub const RWS_CONFIG_TRAFFIC_GEO_DB: &str = "RWS_CONFIG_TRAFFIC_GEO_DB";
10pub const RWS_CONFIG_TRAFFIC_SCRIPT: &str = "RWS_CONFIG_TRAFFIC_SCRIPT";
11pub const RWS_CONFIG_TRAFFIC_GOALS: &str = "RWS_CONFIG_TRAFFIC_GOALS";
12pub const RWS_CONFIG_TRAFFIC_DATABASE_URL_ENV: &str = "RWS_CONFIG_TRAFFIC_DATABASE_URL_ENV";
13pub const RWS_CONFIG_TRAFFIC_HOSTING_NETWORKS: &str = "RWS_CONFIG_TRAFFIC_HOSTING_NETWORKS";
14pub const RWS_CONFIG_TRAFFIC_APPS: &str = "RWS_CONFIG_TRAFFIC_APPS";
15pub const RWS_CONFIG_TRAFFIC_OWNER_NETWORKS: &str = "RWS_CONFIG_TRAFFIC_OWNER_NETWORKS";
16pub const RWS_CONFIG_TRAFFIC_PROBE_ADDRESSES: &str = "RWS_CONFIG_TRAFFIC_PROBE_ADDRESSES";
17pub const RWS_CONFIG_TRAFFIC_HIDE_HOSTS: &str = "RWS_CONFIG_TRAFFIC_HIDE_HOSTS";
18pub const RWS_CONFIG_TRAFFIC_IGNORE_REFERRERS: &str = "RWS_CONFIG_TRAFFIC_IGNORE_REFERRERS";
19
20fn read(key: &str) -> String {
21 std::env::var(key).unwrap_or_default().trim().to_string()
22}
23
24pub fn enabled_setting() -> Option<bool> {
27 match read(RWS_CONFIG_TRAFFIC_ENABLED).to_ascii_lowercase().as_str() {
28 "" => None,
29 "false" | "0" | "no" | "off" => Some(false),
30 _ => Some(true),
31 }
32}
33
34pub fn retention_days() -> u64 {
36 read(RWS_CONFIG_TRAFFIC_RETENTION_DAYS).parse::<u64>().ok().filter(|d| *d >= 1).map_or(30, |d| d.min(90))
37}
38
39pub fn exclude() -> Vec<String> {
42 let value = std::env::var(RWS_CONFIG_TRAFFIC_EXCLUDE);
43 match value {
44 Ok(v) => v.split(',').map(str::trim).filter(|p| !p.is_empty()).map(str::to_string).collect(),
45 Err(_) => ["/healthz", "/readyz", "/metrics"].iter().map(|p| p.to_string()).collect(),
46 }
47}
48
49pub fn persist_path() -> Option<PathBuf> {
54 let value = read(RWS_CONFIG_TRAFFIC_PERSIST);
55 if value.eq_ignore_ascii_case("off") {
56 return None;
57 }
58 if !value.is_empty() {
59 return Some(PathBuf::from(value));
60 }
61 [crate::entry_point::Config::RWS_CONFIG_ACME_CERT_PATH, crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE]
62 .iter()
63 .map(|key| read(key))
64 .find(|path| !path.is_empty())
65 .and_then(|cert| PathBuf::from(cert).parent().map(|dir| dir.join("traffic.json")))
66}
67
68pub fn geo_db() -> Option<PathBuf> {
71 let value = read(RWS_CONFIG_TRAFFIC_GEO_DB);
72 (!value.is_empty()).then(|| PathBuf::from(value))
73}
74
75pub fn script() -> bool {
78 matches!(read(RWS_CONFIG_TRAFFIC_SCRIPT).to_ascii_lowercase().as_str(), "true" | "1" | "yes" | "on")
79}
80
81pub fn hosting_networks() -> bool {
85 !matches!(read(RWS_CONFIG_TRAFFIC_HOSTING_NETWORKS).to_ascii_lowercase().as_str(), "false" | "0" | "no" | "off")
86}
87
88pub const MAX_GOALS: usize = 32;
90
91pub fn goals() -> Vec<String> {
95 read(RWS_CONFIG_TRAFFIC_GOALS).split(',').map(str::trim).filter(|g| !g.is_empty()).take(MAX_GOALS).map(str::to_string).collect()
96}
97
98pub fn database_url() -> Option<String> {
103 let name = read(RWS_CONFIG_TRAFFIC_DATABASE_URL_ENV);
104 if name.is_empty() {
105 return None;
106 }
107 std::env::var(&name).ok().map(|v| v.trim().to_string()).filter(|v| !v.is_empty())
108}
109
110fn list(key: &str) -> Vec<String> {
111 read(key).split(',').map(str::trim).filter(|v| !v.is_empty()).map(str::to_string).collect()
112}
113
114pub fn apps() -> Vec<String> {
118 list(RWS_CONFIG_TRAFFIC_APPS)
119}
120
121pub fn owner_networks() -> Vec<String> {
124 list(RWS_CONFIG_TRAFFIC_OWNER_NETWORKS)
125}
126
127pub fn probe_addresses() -> bool {
131 matches!(read(RWS_CONFIG_TRAFFIC_PROBE_ADDRESSES).to_ascii_lowercase().as_str(), "true" | "1" | "yes" | "on")
132}
133
134pub fn hide_hosts() -> Vec<String> {
137 list(RWS_CONFIG_TRAFFIC_HIDE_HOSTS)
138}
139
140pub fn ignore_referrers() -> Vec<String> {
144 list(RWS_CONFIG_TRAFFIC_IGNORE_REFERRERS)
145}