gen_api_wrapper/
endpoint.rs1use std::borrow::Cow;
12
13use async_trait::async_trait;
14use http::{self, header, Method, Request};
15use serde::de::DeserializeOwned;
16
17use crate::{
18 client::{AsyncClient, Client},
19 error::{ApiError, BodyError},
20 params::QueryParams,
21 query::{self, AsyncQuery, Query},
22};
23
24pub trait Endpoint {
26 fn method(&self) -> Method;
28 fn endpoint(&self) -> Cow<'static, str>;
30
31 fn parameters(&self) -> QueryParams {
33 QueryParams::default()
34 }
35
36 fn body(&self) -> Result<Option<(&'static str, Vec<u8>)>, BodyError> {
40 Ok(None)
41 }
42}
43
44impl<E, T, C> Query<T, C> for E
45where
46 E: Endpoint,
47 T: DeserializeOwned,
48 C: Client,
49{
50 fn query(&self, client: &C) -> Result<T, ApiError<C::Error>> {
51 let mut url = client.rest_endpoint(&self.endpoint())?;
52 self.parameters().add_to_url(&mut url);
53
54 let req = Request::builder()
55 .method(self.method())
56 .uri(query::url_to_http_uri(url));
57 let (req, data) = if let Some((mime, data)) = self.body()? {
58 let req = req.header(header::CONTENT_TYPE, mime);
59 (req, data)
60 } else {
61 (req, Vec::new())
62 };
63 let rsp = client.rest(req, data)?;
64 let status = rsp.status();
65 let v = if let Ok(v) = serde_json::from_slice(rsp.body()) {
66 v
67 } else {
68 return Err(ApiError::server_error(status, rsp.body()));
69 };
70 if !status.is_success() {
71 return Err(ApiError::server_error(status, rsp.body()));
72 }
73
74 serde_json::from_value::<T>(v).map_err(ApiError::data_type::<T>)
75 }
76}
77
78#[async_trait]
79impl<E, T, C> AsyncQuery<T, C> for E
80where
81 E: Endpoint + Sync,
82 T: DeserializeOwned + 'static,
83 C: AsyncClient + Sync,
84{
85 async fn query_async(&self, client: &C) -> Result<T, ApiError<C::Error>> {
86 let mut url = client.rest_endpoint(&self.endpoint())?;
87 self.parameters().add_to_url(&mut url);
88
89 let req = Request::builder()
90 .method(self.method())
91 .uri(query::url_to_http_uri(url));
92 let (req, data) = if let Some((mime, data)) = self.body()? {
93 let req = req.header(header::CONTENT_TYPE, mime);
94 (req, data)
95 } else {
96 (req, Vec::new())
97 };
98 let rsp = client.rest_async(req, data).await?;
99 let status = rsp.status();
100 let v = if let Ok(v) = serde_json::from_slice(rsp.body()) {
101 v
102 } else {
103 return Err(ApiError::server_error(status, rsp.body()));
104 };
105 if !status.is_success() {
106 return Err(ApiError::server_error(status, rsp.body()));
107 }
108
109 serde_json::from_value::<T>(v).map_err(ApiError::data_type::<T>)
110 }
111}