refactor: less code duplication in requests

This commit is contained in:
gak 2023-08-30 13:29:11 +10:00
parent b91b879393
commit ffe00e074b
No known key found for this signature in database

View file

@ -35,6 +35,11 @@ pub struct VehicleId(u64);
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ExternalVehicleId(u64); pub struct ExternalVehicleId(u64);
pub enum MethodWithPayload {
GET,
POST(String),
}
pub struct Api { pub struct Api {
pub access_token: AccessToken, pub access_token: AccessToken,
// TODO: Why is this an Option? // TODO: Why is this an Option?
@ -59,30 +64,20 @@ impl Api {
where where
D: for<'de> Deserialize<'de> + Debug, D: for<'de> Deserialize<'de> + Debug,
{ {
let request = || format!("GET {url}"); let request_context = || format!("GET {url}");
trace!(?url, "Fetching");
let response = self let response = self.request(MethodWithPayload::GET, url).await?;
.client
.get(url)
.header("Authorization", format!("Bearer {}", self.access_token.0))
.header("Accept", "application/json")
.send()
.await
.map_err(|source| TeslatteError::FetchError {
source,
request: request(),
})?;
let body = response let body = response
.text() .text()
.await .await
.map_err(|source| TeslatteError::FetchError { .map_err(|source| TeslatteError::FetchError {
source, source,
request: request(), request: request_context(),
})?; })?;
trace!(?body); trace!(?body);
let data = Self::parse_json::<D, _>(&body, request)?; let data = Self::parse_json::<D, _>(&body, request_context)?;
trace!(?data); trace!(?data);
Ok(Data { data, body }) Ok(Data { data, body })
@ -94,42 +89,29 @@ impl Api {
S: Serialize + Debug, S: Serialize + Debug,
{ {
trace!("Fetching"); trace!("Fetching");
let req_ctx = || {
let payload =
serde_json::to_string(&body).expect("Should not fail creating the request struct.");
format!("POST {} {payload}", &url)
};
let mut request = self.client.post(url).header("Accept", "application/json"); let request_context = || format!("POST {url}");
let auth = true;
if auth { let payload =
request = request.header("Authorization", format!("Bearer {}", self.access_token.0)); serde_json::to_string(&body).expect("Should not fail creating the request struct.");
}
let response = let response = self.request(MethodWithPayload::POST(payload), url).await?;
request
.json(&body)
.send()
.await
.map_err(|source| TeslatteError::FetchError {
source,
request: req_ctx(),
})?;
let body = response let body = response
.text() .text()
.await .await
.map_err(|source| TeslatteError::FetchError { .map_err(|source| TeslatteError::FetchError {
source, source,
request: req_ctx(), request: request_context(),
})?; })?;
let data = Self::parse_json::<PostResponse, _>(&body, req_ctx)?; let data = Self::parse_json::<PostResponse, _>(&body, request_context)?;
trace!(?data); trace!(?data);
if data.result { if data.result {
Ok(Data { data, body }) Ok(Data { data, body })
} else { } else {
Err(TeslatteError::ServerError { Err(TeslatteError::ServerError {
request: req_ctx(), request: request_context(),
msg: data.reason, msg: data.reason,
description: None, description: None,
body: Some(body), body: Some(body),
@ -137,6 +119,34 @@ impl Api {
} }
} }
async fn request(
&self,
method: MethodWithPayload,
url: &str,
) -> Result<reqwest::Response, TeslatteError> {
let request_builder = match &method {
MethodWithPayload::GET => self.client.get(url),
MethodWithPayload::POST(payload) => self
.client
.post(url)
.header("Content-Type", "application/json")
.body(payload.clone()),
};
request_builder
.header("Accept", "application/json")
.header("Authorization", format!("Bearer {}", self.access_token.0))
.send()
.await
.map_err(|source| TeslatteError::FetchError {
source,
request: match method {
MethodWithPayload::GET => format!("GET {url}"),
MethodWithPayload::POST(payload) => format!("POST {url} {payload}"),
},
})
}
// The `request` argument is for additional context in the error. // The `request` argument is for additional context in the error.
fn parse_json<T, F>(body: &str, request: F) -> Result<T, TeslatteError> fn parse_json<T, F>(body: &str, request: F) -> Result<T, TeslatteError>
where where