apolloconfig 0.1.0

apolloconfig
Documentation
//! [Ref](https://www.apolloconfig.com/#/en/usage/other-language-client-user-guide?id=_1412-request-service)

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", &notifications);

        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>)),
}