1use reqwest::{
2 Method, RequestBuilder, Response,
3 header::{AUTHORIZATION, HeaderMap},
4};
5use serde::Serialize;
6
7use crate::{PSNApiResult, models::TokenResponse};
8
9pub struct PSNClient {
11 client: reqwest::Client,
12 pub(crate) npsso: String,
13 pub(crate) cid: String,
14 pub(crate) token_response: Option<TokenResponse>,
15}
16
17impl PSNClient {
18 pub(crate) fn new(client: reqwest::Client, npsso: String) -> Self {
19 PSNClient {
20 client,
21 npsso,
22 cid: uuid::Uuid::new_v4().to_string(),
23 token_response: None,
24 }
25 }
26
27 fn request_builder<U: AsRef<str>, S: Serialize, F: Serialize>(
28 &self,
29 method: Method,
30 url: U,
31 headers: Option<HeaderMap>,
32 query: Option<S>,
33 form: Option<F>,
34 ) -> RequestBuilder {
35 let mut request = self.client.request(method, url.as_ref());
37
38 if let Some(headers) = headers {
39 request = request.headers(headers);
40 }
41 if let Some(query) = query {
42 request = request.query(&query);
43 }
44 if let Some(form) = form {
45 request = request.form(&form);
46 }
47
48 request
49 }
50
51 fn request_builder_authenticated<U: AsRef<str>, S: Serialize, F: Serialize>(
52 &self,
53 method: Method,
54 url: U,
55 headers: Option<HeaderMap>,
56 query: Option<S>,
57 form: Option<F>,
58 ) -> RequestBuilder {
59 let mut authenticated_headers = HeaderMap::new();
60 authenticated_headers.insert(
61 AUTHORIZATION,
62 format!(
63 "Bearer {}",
64 &self.token_response.as_ref().unwrap().access_token
65 )
66 .parse()
67 .unwrap(),
68 );
69
70 if let Some(headers) = headers {
71 authenticated_headers.extend(headers);
72 }
73
74 self.request_builder(method, url, Some(authenticated_headers), query, form)
75 }
76
77 pub(crate) async fn get<U: AsRef<str>>(
78 &self,
79 url: U,
80 headers: Option<HeaderMap>,
81 query: Option<Vec<(&str, &str)>>,
82 ) -> PSNApiResult<Response> {
83 Ok(self
84 .request_builder(Method::GET, url, headers, query, Option::<()>::None)
85 .send()
86 .await?)
87 }
88
89 pub(crate) async fn get_authenticated<U: AsRef<str>, S: Serialize>(
90 &self,
91 url: U,
92 headers: Option<HeaderMap>,
93 query: Option<S>,
94 ) -> PSNApiResult<Response> {
95 let response = self
96 .request_builder_authenticated(Method::GET, url, headers, query, Option::<()>::None)
97 .send()
98 .await?;
99
100 log::debug!("got status code={}", response.status());
101
102 Ok(response)
103 }
104
105 pub(crate) async fn post<U: AsRef<str>, F: Serialize>(
106 &self,
107 url: U,
108 headers: Option<HeaderMap>,
109 form: Option<F>,
110 ) -> PSNApiResult<Response> {
111 Ok(self
112 .request_builder(Method::POST, url, headers, Option::<()>::None, form)
113 .send()
114 .await?)
115 }
116}