Skip to main content

psn_rs/
psn_client.rs

1use reqwest::{
2    Method, RequestBuilder, Response,
3    header::{AUTHORIZATION, HeaderMap},
4};
5use serde::Serialize;
6
7use crate::{PSNApiResult, models::TokenResponse};
8
9/// Main API client.
10pub 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        // TODO: Check if npsso is still valid
36        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}