cloudflare/framework/
async_api.rs

1use crate::framework::{auth, auth::AuthClient, endpoint::Endpoint, ApiResultTraits, Environment};
2use async_trait::async_trait;
3use serde::Serialize;
4use surf::Result;
5
6use serde_json::value::Value as JsonValue;
7
8#[async_trait]
9pub trait AsyncApiClient {
10    async fn request<ResultType, QueryType, BodyType>(
11        &self,
12        endpoint: &(dyn Endpoint<ResultType, QueryType, BodyType> + Send + Sync),
13    ) -> Result<ResultType>
14    where
15        ResultType: ApiResultTraits,
16        QueryType: Serialize,
17        BodyType: Serialize;
18}
19
20/// A Cloudflare API client that makes requests asynchronously.
21pub struct Client {
22    environment: Environment,
23    credentials: auth::Credentials,
24    client: surf::Client,
25}
26
27impl Client {
28    pub fn new(credentials: auth::Credentials, environment: Environment) -> Result<Client> {
29        let client = surf::client();
30        Ok(Client {
31            environment,
32            credentials,
33            client,
34        })
35    }
36}
37
38#[async_trait]
39impl AsyncApiClient for Client {
40    async fn request<ResultType, QueryType, BodyType>(
41        &self,
42        endpoint: &(dyn Endpoint<ResultType, QueryType, BodyType> + Send + Sync),
43    ) -> Result<ResultType>
44    where
45        ResultType: ApiResultTraits,
46        QueryType: Serialize,
47        BodyType: Serialize,
48    {
49        let mut request =
50            surf::RequestBuilder::new(endpoint.method(), endpoint.url(&self.environment));
51
52        request = request.query(&endpoint.query())?;
53        request = request.auth(&self.credentials);
54
55        if let Some(body) = endpoint.body() {
56            request = request.body(surf::Body::from_json(&body)?);
57        }
58
59        let req = request.build();
60        log::debug!("Making {} request to {}", req.method(), req.url());
61        req.iter()
62            .for_each(|header| log::debug!("Request header {}:{}", header.0, header.1));
63
64        let mut res = self.client.send(req).await?;
65        let api_result = res.body_json::<ApiSuccess<ResultType>>().await?;
66
67        Ok(api_result.result)
68    }
69}
70
71#[derive(Deserialize, Debug, PartialEq)]
72pub struct ApiSuccess<ResultType> {
73    pub result: ResultType,
74    pub result_info: Option<JsonValue>,
75    pub messages: JsonValue,
76    pub errors: Vec<JsonValue>,
77}
78
79/*
80async fn map_api_response<ResultType: ApiResultTraits>(resp: surf::Response) -> Result<ResultType> {
81    let status = resp.status();
82    if status.is_success() {
83        let api_result = resp.body_json::<ApiSuccess<ResultType>>().await;
84        match api_result {
85            Ok(res) => Ok(res),
86            Err(e) => Err(ApiFailure::Invalid(e)),
87        }
88    } else {
89        let api_result = res.body_json::<ApiErrors>().await;
90        let errors = api_result.unwrap_or_default();
91        Err(ApiFailure::Error(status, errors))
92    }
93}
94*/