use crate::auth::auth_errors::AuthErrorResponse;
use std::time::Duration;
use std::{collections::HashMap, convert::TryInto};
use reqwest::{Method, RequestBuilder};
use serde_json::Value;
use super::auth_errors::AuthError;
pub type Headers = HashMap<String, String>;
pub type Query<'a> = HashMap<&'a str, &'a str>;
pub type Form<'a> = HashMap<&'a str, &'a str>;
#[derive(Debug, Clone)]
pub struct AuthClient {
client: reqwest::Client,
}
impl Default for AuthClient {
fn default() -> Self {
let client = reqwest::ClientBuilder::new()
.timeout(Duration::from_secs(10))
.build()
.unwrap();
Self { client }
}
}
impl AuthClient {
async fn request<D>(
&self,
method: Method,
url: &str,
headers: Option<&Headers>,
add_data: D,
) -> Result<String, AuthError>
where
D: Fn(RequestBuilder) -> RequestBuilder,
{
let mut request = self.client.request(method.clone(), url);
if let Some(headers) = headers {
let headers = headers.try_into().unwrap();
request = request.headers(headers);
}
request = add_data(request);
log::info!("Making request {:?}", request);
let response = request.send().await?;
let status = response.status();
let resp_text = response.text().await?;
if status.is_success() {
Ok(resp_text)
} else {
let resp_error = serde_json::from_str::<AuthErrorResponse>(&resp_text)?;
Err(AuthError::ResponseError(resp_error))
}
}
}
impl AuthClient {
#[inline]
pub async fn get(
&self,
url: &str,
headers: Option<&Headers>,
query: &Query<'_>,
) -> Result<String, AuthError> {
self.request(Method::GET, url, headers, |req| req.query(query))
.await
}
#[inline]
pub async fn post(
&self,
url: &str,
headers: Option<&Headers>,
query: Option<&Query<'_>>,
payload: &Value,
) -> Result<String, AuthError> {
self.request(Method::POST, url, headers, |req| {
req.query(&query).json(payload)
})
.await
}
#[inline]
pub async fn post_form(
&self,
url: &str,
headers: Option<&Headers>,
payload: &Form<'_>,
) -> Result<String, AuthError> {
self.request(Method::POST, url, headers, |req| req.form(payload))
.await
}
#[inline]
pub async fn put(
&self,
url: &str,
headers: Option<&Headers>,
query: Option<&Query<'_>>,
payload: &Value,
) -> Result<String, AuthError> {
self.request(Method::PUT, url, headers, |req| {
req.query(&query).json(payload)
})
.await
}
#[inline]
pub async fn delete(
&self,
url: &str,
headers: Option<&Headers>,
payload: &Value,
) -> Result<String, AuthError> {
self.request(Method::DELETE, url, headers, |req| req.json(payload))
.await
}
}