zenlayercloud_sdk/
client.rs1use log::debug;
2use serde::{de::DeserializeOwned, Deserialize, Serialize};
3
4use crate::{
5 credentials::AccessKeyCredential,
6 signer::{Signer, Zc2HS256Signer},
7 Error, API_DOMAIN, SDK_VERSION,
8};
9
10#[derive(Debug)]
11pub struct Request {
12 rb: reqwest::RequestBuilder,
13}
14
15impl Request {
16 pub fn build(self) -> reqwest::Result<reqwest::Request> {
17 self.rb.build()
18 }
19}
20
21#[derive(Debug, Deserialize)]
23pub struct Response<T> {
24 #[serde(rename = "requestId")]
25 pub request_id: String,
26 pub response: Option<T>,
28 pub code: Option<String>,
30 pub message: Option<String>,
31}
32
33pub struct Client {
34 hc: reqwest::Client,
35 signer: Zc2HS256Signer,
36}
37
38impl Client {
39 pub fn new(credential: AccessKeyCredential) -> Self {
40 let hc = reqwest::Client::new();
41 let signer = Zc2HS256Signer::new(credential);
42 Client { hc, signer }
43 }
44
45 pub fn create_request<T>(
46 &self,
47 service: &str,
48 api_version: &str,
49 action: &str,
50 payload: &T,
51 ) -> Request
52 where
53 T: Serialize + ?Sized,
54 {
55 let host = API_DOMAIN;
56 let url = format!("https://{}/api/v2/{}", host, service);
57
58 let timestamp = format!("{}", chrono::Local::now().timestamp());
59 let rb = self
60 .hc
61 .post(&url)
62 .header("Host", host)
63 .header("x-zc-version", api_version)
64 .header("x-zc-action", action)
65 .header("x-zc-timestamp", timestamp)
66 .header("x-zc-sdk-version", SDK_VERSION)
67 .header("x-zc-sdk-lang", "rust")
68 .json(payload); Request { rb }
70 }
71
72 pub async fn call_api<R>(&self, req: Request) -> Result<Response<R>, Error>
73 where
74 R: DeserializeOwned,
75 {
76 let mut http_req = req.build()?;
77 self.signer.sign_request(&mut http_req)?;
78 debug!("http_req={:?}", http_req);
79 let http_res = self.hc.execute(http_req).await?;
80 debug!("http_res={:?}", http_res);
81 let status = http_res.status();
82 let res: Response<R> = http_res.json().await?;
83 if status.is_success() {
84 Ok(res)
85 } else {
86 Err(Error::APIError {
87 request_id: res.request_id,
88 http_status: status.as_u16(),
89 code: res.code.unwrap_or_default(),
90 message: res.message.unwrap_or_default(),
91 })
92 }
93 }
94}