use super::client::BuildError;
const DEFAULT_POLLING_BASE_URL: &str = "https://sdk.launchdarkly.com";
const DEFAULT_STREAM_BASE_URL: &str = "https://stream.launchdarkly.com";
const DEFAULT_EVENTS_BASE_URL: &str = "https://events.launchdarkly.com";
pub struct ServiceEndpoints {
polling_base_url: String,
streaming_base_url: String,
events_base_url: String,
}
impl ServiceEndpoints {
pub fn polling_base_url(&self) -> &str {
self.polling_base_url.as_ref()
}
pub fn streaming_base_url(&self) -> &str {
self.streaming_base_url.as_ref()
}
pub fn events_base_url(&self) -> &str {
self.events_base_url.as_ref()
}
}
#[derive(Clone)]
pub struct ServiceEndpointsBuilder {
polling_base_url: Option<String>,
streaming_base_url: Option<String>,
events_base_url: Option<String>,
}
impl ServiceEndpointsBuilder {
pub fn new() -> ServiceEndpointsBuilder {
ServiceEndpointsBuilder {
polling_base_url: None,
streaming_base_url: None,
events_base_url: None,
}
}
pub fn polling_base_url(&mut self, url: &str) -> &mut Self {
self.polling_base_url = Some(String::from(url));
self
}
pub fn streaming_base_url(&mut self, url: &str) -> &mut Self {
self.streaming_base_url = Some(String::from(url));
self
}
pub fn events_base_url(&mut self, url: &str) -> &mut Self {
self.events_base_url = Some(String::from(url));
self
}
pub fn relay_proxy(&mut self, url: &str) -> &mut Self {
self.polling_base_url = Some(String::from(url));
self.streaming_base_url = Some(String::from(url));
self.events_base_url = Some(String::from(url));
self
}
pub fn build(&self) -> Result<ServiceEndpoints, BuildError> {
match (
&self.polling_base_url,
&self.streaming_base_url,
&self.events_base_url,
) {
(Some(polling_base_url), Some(streaming_base_url), Some(events_base_url)) => {
Ok(ServiceEndpoints {
polling_base_url: polling_base_url.trim_end_matches('/').to_string(),
streaming_base_url: streaming_base_url.trim_end_matches('/').to_string(),
events_base_url: events_base_url.trim_end_matches('/').to_string(),
})
}
(None, None, None) => Ok(ServiceEndpoints {
polling_base_url: String::from(DEFAULT_POLLING_BASE_URL),
streaming_base_url: String::from(DEFAULT_STREAM_BASE_URL),
events_base_url: String::from(DEFAULT_EVENTS_BASE_URL),
}),
_ => Err(BuildError::InvalidConfig(
"If you specify any endpoints,\
then you must specify all endpoints."
.into(),
)),
}
}
}
impl Default for ServiceEndpointsBuilder {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
use test_case::test_case;
#[test_case("localhost", "localhost"; "requires no trimming")]
#[test_case("http://localhost", "http://localhost"; "requires no trimming with scheme")]
#[test_case("localhost/", "localhost"; "trims trailing slash")]
#[test_case("http://localhost/", "http://localhost"; "trims trailing slash with scheme")]
#[test_case("localhost////////", "localhost"; "trims multiple trailing slashes")]
fn service_endpoints_trims_base_urls(url: &str, expected: &str) {
let endpoints = ServiceEndpointsBuilder::new()
.polling_base_url(url)
.streaming_base_url(url)
.events_base_url(url)
.build()
.expect("Provided URLs should parse successfully");
assert_eq!(expected, endpoints.events_base_url());
assert_eq!(expected, endpoints.streaming_base_url());
assert_eq!(expected, endpoints.polling_base_url());
}
#[test]
fn default_configuration() -> Result<(), BuildError> {
let endpoints = ServiceEndpointsBuilder::new().build()?;
assert_eq!(
"https://events.launchdarkly.com",
endpoints.events_base_url()
);
assert_eq!(
"https://stream.launchdarkly.com",
endpoints.streaming_base_url()
);
assert_eq!("https://sdk.launchdarkly.com", endpoints.polling_base_url());
Ok(())
}
#[test]
fn full_custom_configuration() -> Result<(), BuildError> {
let endpoints = ServiceEndpointsBuilder::new()
.polling_base_url("https://sdk.my-private-instance.com")
.streaming_base_url("https://stream.my-private-instance.com")
.events_base_url("https://events.my-private-instance.com")
.build()?;
assert_eq!(
"https://events.my-private-instance.com",
endpoints.events_base_url()
);
assert_eq!(
"https://stream.my-private-instance.com",
endpoints.streaming_base_url()
);
assert_eq!(
"https://sdk.my-private-instance.com",
endpoints.polling_base_url()
);
Ok(())
}
#[test]
fn partial_definition() {
assert!(ServiceEndpointsBuilder::new()
.polling_base_url("https://sdk.my-private-instance.com")
.build()
.is_err());
}
#[test]
fn configure_relay_proxy() -> Result<(), BuildError> {
let endpoints = ServiceEndpointsBuilder::new()
.relay_proxy("http://my-relay-hostname:8080")
.build()?;
assert_eq!("http://my-relay-hostname:8080", endpoints.events_base_url());
assert_eq!(
"http://my-relay-hostname:8080",
endpoints.streaming_base_url()
);
assert_eq!(
"http://my-relay-hostname:8080",
endpoints.polling_base_url()
);
Ok(())
}
}