use apolloconfig_sig::AuthSignature;
use http_api_client_endpoint::{
http::{
header::{ACCEPT, USER_AGENT},
Method, StatusCode,
},
Body, Endpoint, Request, Response, MIME_APPLICATION_JSON,
};
use url::Url;
use crate::{
endpoints::{common::EndpointError, CLUSTER_NAME_DEFAULT},
objects::{notification::Notifications, ResponseBodyErrJson},
};
#[derive(Debug, Clone)]
pub struct NotificationsV2 {
pub config_server_url: Box<str>,
pub access_key_secret: Box<str>,
pub app_id: Box<str>,
pub cluster_name: Option<Box<str>>,
pub notifications: Notifications,
}
impl NotificationsV2 {
pub fn new(
config_server_url: impl AsRef<str>,
access_key_secret: impl AsRef<str>,
app_id: impl AsRef<str>,
notifications: &Notifications,
) -> Self {
Self {
config_server_url: config_server_url.as_ref().into(),
access_key_secret: access_key_secret.as_ref().into(),
app_id: app_id.as_ref().into(),
cluster_name: None,
notifications: notifications.to_owned(),
}
}
pub fn cluster_name(mut self, value: impl AsRef<str>) -> Self {
self.cluster_name = Some(value.as_ref().into());
self
}
}
impl Endpoint for NotificationsV2 {
type RenderRequestError = EndpointError;
type ParseResponseOutput = NotificationsV2EndpointRet;
type ParseResponseError = EndpointError;
fn render_request(&self) -> Result<Request<Body>, Self::RenderRequestError> {
let mut url =
Url::parse(&self.config_server_url).map_err(EndpointError::MakeRequestUrlFailed)?;
let path = "/notifications/v2";
url.set_path(path);
url.query_pairs_mut()
.append_pair("appId", self.app_id.as_ref());
url.query_pairs_mut().append_pair(
"cluster",
self.cluster_name.as_deref().unwrap_or(CLUSTER_NAME_DEFAULT),
);
let notifications = serde_json::to_string(&self.notifications)
.map_err(EndpointError::MakeRequestQueryFailed)?;
url.query_pairs_mut()
.append_pair("notifications", ¬ifications);
let auth_headers = AuthSignature
.http_headers(url.as_str(), &self.app_id, &self.access_key_secret)
.map_err(EndpointError::MakeSignatureFailed)?;
let request_builder = Request::builder()
.method(Method::GET)
.uri(url.as_str())
.header(USER_AGENT, "apolloconfig-rs")
.header(ACCEPT, MIME_APPLICATION_JSON);
let request_builder = auth_headers
.into_iter()
.flat_map(|(k, v)| k.map(|k| (k, v)))
.fold(request_builder, |request_builder, (k, v)| {
request_builder.header(k, v)
});
let request = request_builder
.body(vec![])
.map_err(EndpointError::MakeRequestFailed)?;
Ok(request)
}
fn parse_response(
&self,
response: Response<Body>,
) -> Result<Self::ParseResponseOutput, Self::ParseResponseError> {
let status = response.status();
match status {
StatusCode::OK => Ok(NotificationsV2EndpointRet::Ok(
serde_json::from_slice(response.body())
.map_err(EndpointError::DeResponseBodyOkJsonFailed)?,
)),
StatusCode::NOT_MODIFIED => Ok(NotificationsV2EndpointRet::NotChanged),
status => match serde_json::from_slice::<ResponseBodyErrJson>(response.body()) {
Ok(err_json) => Ok(NotificationsV2EndpointRet::Other((status, Ok(err_json)))),
Err(_) => Ok(NotificationsV2EndpointRet::Other((
status,
Err(response.body().to_owned()),
))),
},
}
}
}
#[derive(Debug, Clone)]
pub enum NotificationsV2EndpointRet {
Ok(Notifications),
NotChanged,
Other((StatusCode, Result<ResponseBodyErrJson, Body>)),
}