1use std::fmt;
2
3pub const US_INGESTION_ENDPOINT: &str = "https://us.i.posthog.com";
5
6pub const EU_INGESTION_ENDPOINT: &str = "https://eu.i.posthog.com";
8
9pub const DEFAULT_HOST: &str = US_INGESTION_ENDPOINT;
11
12#[derive(Debug, Clone)]
14pub enum Endpoint {
15 Capture,
17 Batch,
19 Flags,
21 LocalEvaluation,
23}
24
25impl Endpoint {
26 pub fn path(&self) -> &str {
28 match self {
29 Endpoint::Capture => "/i/v0/e/",
30 Endpoint::Batch => "/batch/",
31 Endpoint::Flags => "/flags/?v=2",
32 Endpoint::LocalEvaluation => "/flags/definitions/?send_cohorts",
33 }
34 }
35}
36
37impl fmt::Display for Endpoint {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 write!(f, "{}", self.path())
40 }
41}
42
43#[derive(Debug, Clone)]
49pub struct EndpointManager {
50 base_host: String,
51 raw_host: String,
52}
53
54impl EndpointManager {
55 pub fn new(host: String) -> Self {
60 let base_host = Self::determine_server_host(&host);
61
62 Self {
63 base_host,
64 raw_host: host,
65 }
66 }
67
68 pub fn determine_server_host(host: &str) -> String {
74 let trimmed_host = host.trim_end_matches('/');
75
76 match trimmed_host {
77 "https://app.posthog.com" | "https://us.posthog.com" => {
78 US_INGESTION_ENDPOINT.to_string()
79 }
80 "https://eu.posthog.com" => EU_INGESTION_ENDPOINT.to_string(),
81 _ => trimmed_host.to_string(),
82 }
83 }
84
85 pub fn base_host(&self) -> &str {
87 &self.base_host
88 }
89
90 pub fn raw_host(&self) -> &str {
92 &self.raw_host
93 }
94
95 pub fn build_url(&self, endpoint: Endpoint) -> String {
97 format!(
98 "{}{}",
99 self.base_host.trim_end_matches('/'),
100 endpoint.path()
101 )
102 }
103
104 pub fn build_custom_url(&self, path: &str) -> String {
108 let normalized_path = if path.starts_with('/') {
109 path.to_string()
110 } else {
111 format!("/{path}")
112 };
113 format!(
114 "{}{}",
115 self.base_host.trim_end_matches('/'),
116 normalized_path
117 )
118 }
119
120 pub fn build_local_eval_url(&self, token: &str) -> String {
125 format!(
126 "{}/flags/definitions/?token={}&send_cohorts",
127 self.base_host.trim_end_matches('/'),
128 token
129 )
130 }
131
132 pub fn api_host(&self) -> String {
134 self.base_host.trim_end_matches('/').to_string()
135 }
136}
137
138#[cfg(test)]
139mod tests {
140 use super::*;
141
142 #[test]
143 fn test_determine_server_host() {
144 assert_eq!(
145 EndpointManager::determine_server_host("https://app.posthog.com"),
146 US_INGESTION_ENDPOINT
147 );
148
149 assert_eq!(
150 EndpointManager::determine_server_host("https://us.posthog.com"),
151 US_INGESTION_ENDPOINT
152 );
153
154 assert_eq!(
155 EndpointManager::determine_server_host("https://eu.posthog.com"),
156 EU_INGESTION_ENDPOINT
157 );
158
159 assert_eq!(
160 EndpointManager::determine_server_host("https://custom.domain.com"),
161 "https://custom.domain.com"
162 );
163
164 assert_eq!(
165 EndpointManager::determine_server_host("https://eu.posthog.com/"),
166 EU_INGESTION_ENDPOINT
167 );
168 }
169
170 #[test]
171 fn test_build_url() {
172 let manager = EndpointManager::new(DEFAULT_HOST.to_string());
173
174 assert_eq!(
175 manager.build_url(Endpoint::Capture),
176 format!("{}/i/v0/e/", US_INGESTION_ENDPOINT)
177 );
178
179 assert_eq!(
180 manager.build_url(Endpoint::Flags),
181 format!("{}/flags/?v=2", US_INGESTION_ENDPOINT)
182 );
183 }
184
185 #[test]
186 fn test_build_custom_url() {
187 let manager = EndpointManager::new("https://custom.com/".to_string());
188
189 assert_eq!(
190 manager.build_custom_url("/api/test"),
191 "https://custom.com/api/test"
192 );
193
194 assert_eq!(
195 manager.build_custom_url("api/test"),
196 "https://custom.com/api/test"
197 );
198 }
199}