openapi_rs/common/
client.rs1use 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 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}