apollo_client/open/
mod.rs

1//! Apollo Open APIs apis.
2//!
3//! Ref: <https://www.apolloconfig.com/#/zh/usage/apollo-open-api-platform>.
4//!
5//! Call open platform api to fetch app infos:
6//!
7//! ```
8//! use apollo_client::open::{requests::OpenAppRequest, OpenApiClientBuilder};
9//! use std::error::Error;
10//!
11//! #[tokio::main]
12//! async fn main() -> Result<(), Box<dyn Error>> {
13//!     env_logger::init();
14//!
15//!     // Create open platform api client.
16//!     let client = OpenApiClientBuilder::new(
17//!         "http://127.0.0.1:8070/".parse()?,
18//!         "391cc4053f8cce2e452a0e6db8925bbba503f434",
19//!     )?
20//!     .build()?;
21//!
22//!     // Execute app fetching request.
23//!     let responses = client
24//!         .app(OpenAppRequest {
25//!             app_ids: Some(vec!["SampleApp".into()]),
26//!         })
27//!         .await?;
28//!
29//!     dbg!(responses);
30//!
31//!     Ok(())
32//! }
33//! ```
34
35pub mod meta;
36pub mod requests;
37pub mod responses;
38
39use crate::{
40    errors::ApolloClientResult,
41    meta::{handle_url, validate_response, PerformResponse, DEFAULT_TIMEOUT},
42    open::{
43        requests::{
44            OpenAppRequest, OpenClusterRequest, OpenCreateItemRequest, OpenEnvClusterRequest,
45            OpenNamespaceRequest, OpenPublishNamespaceRequest, OpenUpdateItemRequest,
46            PerformOpenRequest,
47        },
48        responses::{
49            OpenAppResponse, OpenClusterResponse, OpenEnvClusterResponse, OpenItemResponse,
50            OpenNamespaceResponse, OpenPublishResponse,
51        },
52    },
53};
54use http::{header::AUTHORIZATION, HeaderMap, HeaderValue};
55use reqwest::{Client, ClientBuilder};
56use url::Url;
57
58/// The builder for [OpenApiClient].
59pub struct OpenApiClientBuilder {
60    portal_url: Url,
61    token: String,
62    client_builder: ClientBuilder,
63}
64
65impl OpenApiClientBuilder {
66    /// Create a builder.
67    pub fn new(portal_url: Url, token: impl ToString) -> ApolloClientResult<Self> {
68        let mut builder = Self {
69            portal_url,
70            token: token.to_string(),
71            client_builder: Default::default(),
72        };
73        let default_headers = builder.default_headers()?;
74        builder.client_builder = builder
75            .client_builder
76            .timeout(DEFAULT_TIMEOUT)
77            .default_headers(default_headers);
78        Ok(builder)
79    }
80
81    /// Customize inner http client.
82    ///
83    /// # Example
84    ///
85    /// ```no_run
86    /// use apollo_client::open::OpenApiClientBuilder;
87    /// use std::time::Duration;
88    ///
89    /// OpenApiClientBuilder::new(
90    ///     "http://127.0.0.1:8070/".parse().unwrap(),
91    ///     "391cc4053f8cce2e452a0e6db8925bbba503f434",
92    /// )
93    /// .unwrap()
94    /// .with_client_builder(|builder| builder.timeout(Duration::from_secs(6)));
95    /// ```
96    pub fn with_client_builder(mut self, f: impl FnOnce(ClientBuilder) -> ClientBuilder) -> Self {
97        self.client_builder = f(self.client_builder);
98        self
99    }
100
101    /// Build the [OpenApiClient].
102    pub fn build(self) -> ApolloClientResult<OpenApiClient> {
103        Ok(OpenApiClient {
104            portal_url: self.portal_url,
105            client: self.client_builder.build()?,
106        })
107    }
108
109    fn default_headers(&self) -> Result<HeaderMap, http::Error> {
110        let mut map = HeaderMap::new();
111        map.insert(AUTHORIZATION, HeaderValue::from_str(&self.token)?);
112        Ok(map)
113    }
114}
115
116/// Created by [OpenApiClientBuilder::build].
117pub struct OpenApiClient {
118    portal_url: Url,
119    client: Client,
120}
121
122impl OpenApiClient {
123    /// 获取App的环境,集群信息。
124    ///
125    /// [Ref](https://www.apolloconfig.com/#/zh/usage/apollo-open-api-platform?id=_321-%e8%8e%b7%e5%8f%96app%e7%9a%84%e7%8e%af%e5%a2%83%ef%bc%8c%e9%9b%86%e7%be%a4%e4%bf%a1%e6%81%af)
126    pub async fn env_cluster(
127        &self,
128        request: OpenEnvClusterRequest,
129    ) -> ApolloClientResult<Vec<OpenEnvClusterResponse>> {
130        self.execute(request).await
131    }
132
133    /// 获取App信息。
134    ///
135    /// [Ref](https://www.apolloconfig.com/#/zh/usage/apollo-open-api-platform?id=_322-%e8%8e%b7%e5%8f%96app%e4%bf%a1%e6%81%af)
136    pub async fn app(&self, request: OpenAppRequest) -> ApolloClientResult<Vec<OpenAppResponse>> {
137        self.execute(request).await
138    }
139
140    /// 获取集群接口。
141    ///
142    /// [Ref](https://www.apolloconfig.com/#/zh/usage/apollo-open-api-platform?id=_323-%e8%8e%b7%e5%8f%96%e9%9b%86%e7%be%a4%e6%8e%a5%e5%8f%a3)
143    pub async fn cluster(
144        &self,
145        request: OpenClusterRequest,
146    ) -> ApolloClientResult<OpenClusterResponse> {
147        self.execute(request).await
148    }
149
150    /// 获取某个Namespace信息接口。
151    ///
152    /// [Ref](https://www.apolloconfig.com/#/zh/usage/apollo-open-api-platform?id=_326-%e8%8e%b7%e5%8f%96%e6%9f%90%e4%b8%aanamespace%e4%bf%a1%e6%81%af%e6%8e%a5%e5%8f%a3)
153    pub async fn namespace(
154        &self,
155        request: OpenNamespaceRequest,
156    ) -> ApolloClientResult<Vec<OpenNamespaceResponse>> {
157        self.execute(request).await
158    }
159
160    /// 新增配置接口。
161    ///
162    /// [Ref](https://www.apolloconfig.com/#/zh/usage/apollo-open-api-platform?id=_3210-%e6%96%b0%e5%a2%9e%e9%85%8d%e7%bd%ae%e6%8e%a5%e5%8f%a3)
163    pub async fn create_item(
164        &self,
165        request: OpenCreateItemRequest,
166    ) -> ApolloClientResult<OpenItemResponse> {
167        self.execute(request).await
168    }
169
170    /// 修改配置接口。
171    ///
172    /// [Ref](https://www.apolloconfig.com/#/zh/usage/apollo-open-api-platform?id=_3211-%e4%bf%ae%e6%94%b9%e9%85%8d%e7%bd%ae%e6%8e%a5%e5%8f%a3)
173    pub async fn update_item(&self, request: OpenUpdateItemRequest) -> ApolloClientResult<()> {
174        self.execute(request).await
175    }
176
177    /// 发布配置接口。
178    ///
179    /// [Ref](https://www.apolloconfig.com/#/zh/usage/apollo-open-api-platform?id=_3213-%e5%8f%91%e5%b8%83%e9%85%8d%e7%bd%ae%e6%8e%a5%e5%8f%a3)
180    pub async fn publish_namespace(
181        &self,
182        request: OpenPublishNamespaceRequest,
183    ) -> ApolloClientResult<OpenPublishResponse> {
184        self.execute(request).await
185    }
186
187    async fn execute<R: PerformResponse>(
188        &self,
189        request: impl PerformOpenRequest<Response = R>,
190    ) -> ApolloClientResult<R> {
191        let url = handle_url(&request, self.portal_url.clone())?;
192        let mut request_builder = self.client.request(request.method(), url);
193        request_builder = request.request_builder(request_builder);
194        let response = request_builder.send().await?;
195        let response = validate_response(response).await?;
196        <R>::from_response(response).await
197    }
198}