openapi_rs/common/
client.rs

1use crate::common::config::{EndpointType, OpenApiConfig};
2use crate::common::define::{BaseRequest, HttpFn};
3use crate::common::request::HttpBuilder;
4use crate::common::signer::Signer;
5use crate::common::time::current_timestamp;
6use reqwest::header::{HeaderMap, HeaderName, HeaderValue};
7use std::collections::HashMap;
8use std::env;
9
10#[derive(Debug, Default)]
11pub struct OpenApiClient {
12    config: OpenApiConfig,
13    signer: Signer,
14
15    endpoint_type: EndpointType,
16}
17
18impl OpenApiClient {
19    pub fn new(open_api_config: OpenApiConfig) -> Self {
20        let app_key = open_api_config.app_key.clone();
21        let app_secret = open_api_config.app_secret.clone();
22        Self {
23            config: open_api_config,
24            signer: Signer::new(&app_key, &app_secret),
25            ..Default::default()
26        }
27    }
28
29    pub fn with_endpoint_type(mut self, endpoint_type: EndpointType) -> Self {
30        self.endpoint_type = endpoint_type;
31        self
32    }
33
34    pub async fn send<R>(&mut self, http_fn: HttpFn<R>) -> anyhow::Result<R>
35    where
36        R: std::fmt::Debug + Send + 'static,
37    {
38        let (req_fn, resp_fn) = http_fn();
39        let mut base_request = req_fn();
40
41        dbg!(&base_request);
42
43        self.default_headers_queries(&mut base_request)?;
44
45        let endpoint = match self.endpoint_type {
46            EndpointType::Api => self.config.endpoint.clone(),
47            EndpointType::Cloud => self.config.cloud_endpoint.clone(),
48            EndpointType::Hpc => self.config.hpc_endpoint.clone(),
49            EndpointType::Sync => self.config.sync_endpoint.clone(),
50        };
51
52        let response = HttpBuilder::new()
53            .with_base_url(endpoint)
54            .with_base_request(base_request)
55            .builder()?
56            .send()
57            .await?;
58
59        dbg!(&response);
60
61        resp_fn(response).await
62    }
63
64    fn default_headers_queries(
65        &mut self,
66        base_request: &mut BaseRequest,
67    ) -> Result<(), anyhow::Error> {
68        let mut headers = HeaderMap::new();
69        for (k, v) in default_headers(&self.config)? {
70            headers.insert(
71                HeaderName::from_bytes(k.as_bytes())?,
72                HeaderValue::from_str(&v)?,
73            );
74        }
75        base_request.headers.iter().for_each(|(k, v)| {
76            headers.insert(k, v.clone());
77        });
78        if base_request.content_type.is_none() {
79            base_request.content_type = Some("application/octet-stream".to_string())
80        }
81        headers.insert(
82            HeaderName::from_bytes("Content-Type".as_bytes())?,
83            HeaderValue::from_str(base_request.content_type.as_ref().unwrap())?,
84        );
85
86        let mut default_queries = default_queries(&self.config)?;
87        if let Some(ref queries) = base_request.queries {
88            queries.iter().for_each(|(k, v)| {
89                default_queries.insert(k.to_string(), v.to_string());
90            });
91        }
92
93        // signature
94        let signature = self.signer.sign_request(base_request, &default_queries)?;
95        default_queries.insert("Signature".to_string(), signature.to_string());
96
97        base_request.headers = headers.clone();
98        let x_ys_version = env::var("XYsVersion")?;
99        default_queries.insert("X-Ys-Version".to_string(), x_ys_version);
100        base_request.queries = Some(default_queries.clone());
101
102        Ok(())
103    }
104}
105
106fn default_headers(config: &OpenApiConfig) -> anyhow::Result<HashMap<String, String>> {
107    let mut headers = HashMap::new();
108    let user_id = config.user_id.clone();
109    headers.insert("x-ys-user-id".to_string(), user_id);
110    let x_ys_version = env::var("XYsVersion")?;
111    headers.insert("X-Ys-Version".to_string(), x_ys_version);
112    Ok(headers)
113}
114
115fn default_queries(config: &OpenApiConfig) -> anyhow::Result<HashMap<String, String>> {
116    let mut queries = HashMap::new();
117    let app_key = config.app_key.clone();
118    queries.insert("AppKey".to_string(), app_key);
119    let x_ys_version = env::var("XYsVersion")?;
120    queries.insert("X-Ys-Version".to_string(), x_ys_version);
121    let timestamp = current_timestamp()?;
122    queries.insert("Timestamp".to_string(), timestamp);
123    Ok(queries)
124}