use crate::{
conf::{
meta::{IpValue, Notification},
responses::FetchResponse,
},
errors::ApolloClientResult,
meta::{PerformRequest, DEFAULT_CLUSTER_NAME, DEFAULT_NOTIFY_TIMEOUT},
};
use ini::Properties;
use reqwest::RequestBuilder;
use std::{borrow::Cow, time::Duration};
pub(crate) trait PerformConfRequest: PerformRequest {}
#[derive(Clone, Debug)]
pub struct CachedFetchRequest {
pub app_id: String,
pub namespace_name: String,
pub ip: Option<IpValue>,
pub cluster_name: String,
pub extras_queries: Vec<(String, String)>,
#[cfg(feature = "auth")]
#[cfg_attr(docsrs, doc(cfg(feature = "auth")))]
pub access_key: Option<String>,
}
impl Default for CachedFetchRequest {
fn default() -> Self {
Self {
app_id: "".to_string(),
namespace_name: "".to_string(),
ip: None,
cluster_name: DEFAULT_CLUSTER_NAME.to_string(),
extras_queries: vec![],
#[cfg(feature = "auth")]
access_key: None,
}
}
}
impl PerformRequest for CachedFetchRequest {
type Response = Properties;
fn path(&self) -> String {
format!(
"/configfiles/{app_id}/{cluster_name}/{namespace_name}",
app_id = self.app_id,
cluster_name = self.cluster_name,
namespace_name = self.namespace_name
)
}
fn queries(&self) -> ApolloClientResult<Vec<(Cow<'static, str>, Cow<'static, str>)>> {
let mut pairs = vec![];
if let Some(ip) = &self.ip {
pairs.push(("ip".into(), ip.to_string().into()));
}
if !self.extras_queries.is_empty() {
pairs.extend(
self.extras_queries
.iter()
.map(|(k, v)| (k.clone().into(), v.clone().into())),
);
}
Ok(pairs)
}
fn app_id(&self) -> Option<&str> {
Some(&self.app_id)
}
#[cfg(feature = "auth")]
fn access_key(&self) -> Option<&str> {
self.access_key.as_deref()
}
}
impl PerformConfRequest for CachedFetchRequest {}
#[derive(Clone, Debug)]
pub struct FetchRequest {
pub app_id: String,
pub namespace_name: String,
pub cluster_name: String,
pub ip: Option<IpValue>,
pub release_key: Option<String>,
pub extras_queries: Vec<(String, String)>,
#[cfg(feature = "auth")]
#[cfg_attr(docsrs, doc(cfg(feature = "auth")))]
pub access_key: Option<String>,
}
impl Default for FetchRequest {
fn default() -> Self {
FetchRequest {
app_id: "".to_string(),
namespace_name: "".to_string(),
cluster_name: DEFAULT_CLUSTER_NAME.to_string(),
ip: None,
release_key: None,
extras_queries: vec![],
#[cfg(feature = "auth")]
access_key: None,
}
}
}
impl FetchRequest {
pub(crate) fn namespace_name(&self) -> String {
self.namespace_name.to_string()
}
pub(crate) fn from_watch(watch: &WatchRequest, namespace_name: String) -> Self {
Self {
app_id: watch.app_id.clone(),
cluster_name: watch.cluster_name.clone(),
namespace_name,
ip: watch.ip.clone(),
release_key: None,
extras_queries: watch.extras_queries.clone(),
#[cfg(feature = "auth")]
access_key: watch.access_key.clone(),
}
}
}
impl PerformRequest for FetchRequest {
type Response = FetchResponse;
fn path(&self) -> String {
format!(
"/configs/{app_id}/{cluster_name}/{namespace_name}",
app_id = self.app_id,
cluster_name = self.cluster_name,
namespace_name = self.namespace_name
)
}
fn queries(&self) -> ApolloClientResult<Vec<(Cow<'_, str>, Cow<'_, str>)>> {
let mut pairs = vec![];
if let Some(ip) = &self.ip {
pairs.push(("ip".into(), ip.to_string().into()));
}
if let Some(release_key) = &self.release_key {
pairs.push(("releaseKey".into(), release_key.clone().into()));
}
if !self.extras_queries.is_empty() {
pairs.extend(
self.extras_queries
.iter()
.map(|(k, v)| (k.clone().into(), v.clone().into())),
);
}
Ok(pairs)
}
fn app_id(&self) -> Option<&str> {
Some(&self.app_id)
}
#[cfg(feature = "auth")]
fn access_key(&self) -> Option<&str> {
self.access_key.as_deref()
}
}
impl PerformConfRequest for FetchRequest {}
#[derive(Clone, Debug)]
pub struct NotifyRequest {
pub app_id: String,
pub notifications: Vec<Notification>,
pub cluster_name: String,
pub timeout: Duration,
#[cfg(feature = "auth")]
#[cfg_attr(docsrs, doc(cfg(feature = "auth")))]
pub access_key: Option<String>,
}
impl Default for NotifyRequest {
fn default() -> Self {
NotifyRequest {
app_id: "".to_string(),
notifications: vec![],
cluster_name: DEFAULT_CLUSTER_NAME.to_string(),
timeout: DEFAULT_NOTIFY_TIMEOUT,
#[cfg(feature = "auth")]
access_key: None,
}
}
}
impl NotifyRequest {
pub(crate) fn from_watch(
watch: &WatchRequest,
notifications: Vec<Notification>,
timeout: Duration,
) -> Self {
Self {
app_id: watch.app_id.clone(),
cluster_name: watch.cluster_name.clone(),
notifications,
timeout,
#[cfg(feature = "auth")]
access_key: watch.access_key.clone(),
}
}
}
impl PerformRequest for NotifyRequest {
type Response = Vec<Notification>;
fn path(&self) -> String {
"/notifications/v2".to_string()
}
fn queries(&self) -> ApolloClientResult<Vec<(Cow<'_, str>, Cow<'_, str>)>> {
let notifications = &self.notifications;
Ok(vec![
("appId".into(), self.app_id.clone().into()),
("cluster".into(), self.cluster_name.clone().into()),
(
"notifications".into(),
serde_json::to_string(notifications)?.into(),
),
])
}
#[allow(unused_mut)]
fn request_builder(&self, mut request_builder: RequestBuilder) -> RequestBuilder {
#[cfg(feature = "auth")]
{
request_builder = self.signature(request_builder);
}
request_builder.timeout(self.timeout)
}
fn app_id(&self) -> Option<&str> {
Some(&self.app_id)
}
#[cfg(feature = "auth")]
fn access_key(&self) -> Option<&str> {
self.access_key.as_deref()
}
}
impl PerformConfRequest for NotifyRequest {}
#[derive(Clone, Debug)]
pub struct WatchRequest {
pub app_id: String,
pub namespace_names: Vec<String>,
pub cluster_name: String,
pub ip: Option<IpValue>,
pub extras_queries: Vec<(String, String)>,
#[cfg(feature = "auth")]
pub access_key: Option<String>,
}
impl Default for WatchRequest {
fn default() -> Self {
WatchRequest {
app_id: "".to_string(),
namespace_names: vec![],
cluster_name: DEFAULT_CLUSTER_NAME.to_string(),
ip: None,
extras_queries: vec![],
#[cfg(feature = "auth")]
access_key: None,
}
}
}
impl WatchRequest {
pub(crate) fn create_notifications(&self) -> Vec<Notification> {
self.namespace_names
.iter()
.map(|namespace| Notification {
namespace_name: namespace.clone(),
..Default::default()
})
.collect()
}
}