use reqwest::{
Method, RequestBuilder, Response,
header::{AUTHORIZATION, HeaderMap},
};
use serde::Serialize;
use crate::{PSNApiResult, models::TokenResponse};
pub struct PSNClient {
client: reqwest::Client,
pub(crate) npsso: String,
pub(crate) cid: String,
pub(crate) token_response: Option<TokenResponse>,
}
impl PSNClient {
pub(crate) fn new(client: reqwest::Client, npsso: String) -> Self {
PSNClient {
client,
npsso,
cid: uuid::Uuid::new_v4().to_string(),
token_response: None,
}
}
fn request_builder<U: AsRef<str>, S: Serialize, F: Serialize>(
&self,
method: Method,
url: U,
headers: Option<HeaderMap>,
query: Option<S>,
form: Option<F>,
) -> RequestBuilder {
let mut request = self.client.request(method, url.as_ref());
if let Some(headers) = headers {
request = request.headers(headers);
}
if let Some(query) = query {
request = request.query(&query);
}
if let Some(form) = form {
request = request.form(&form);
}
request
}
fn request_builder_authenticated<U: AsRef<str>, S: Serialize, F: Serialize>(
&self,
method: Method,
url: U,
headers: Option<HeaderMap>,
query: Option<S>,
form: Option<F>,
) -> RequestBuilder {
let mut authenticated_headers = HeaderMap::new();
authenticated_headers.insert(
AUTHORIZATION,
format!(
"Bearer {}",
&self.token_response.as_ref().unwrap().access_token
)
.parse()
.unwrap(),
);
if let Some(headers) = headers {
authenticated_headers.extend(headers);
}
self.request_builder(method, url, Some(authenticated_headers), query, form)
}
pub(crate) async fn get<U: AsRef<str>>(
&self,
url: U,
headers: Option<HeaderMap>,
query: Option<Vec<(&str, &str)>>,
) -> PSNApiResult<Response> {
Ok(self
.request_builder(Method::GET, url, headers, query, Option::<()>::None)
.send()
.await?)
}
pub(crate) async fn get_authenticated<U: AsRef<str>, S: Serialize>(
&self,
url: U,
headers: Option<HeaderMap>,
query: Option<S>,
) -> PSNApiResult<Response> {
let response = self
.request_builder_authenticated(Method::GET, url, headers, query, Option::<()>::None)
.send()
.await?;
log::debug!("got status code={}", response.status());
Ok(response)
}
pub(crate) async fn post<U: AsRef<str>, F: Serialize>(
&self,
url: U,
headers: Option<HeaderMap>,
form: Option<F>,
) -> PSNApiResult<Response> {
Ok(self
.request_builder(Method::POST, url, headers, Option::<()>::None, form)
.send()
.await?)
}
}