1use crate::{
2 error::{Error, Result},
3 request::Login,
4 response::access_token::AccessToken,
5 Action,
6};
7use reqwest::{header::CONTENT_TYPE, Client as ReqwestClient, Response};
8
9#[derive(Clone, Debug)]
10pub struct Client {
11 pub client: ReqwestClient,
12 pub token: Option<String>,
13 pub hostname: String,
14 pub password: String,
15 pub username: String,
16}
17
18impl Client {
19 pub fn new(hostname: String, username: String, password: String) -> Self {
20 let client = ReqwestClient::new();
21 Client {
22 client,
23 token: None,
24 hostname,
25 password,
26 username,
27 }
28 }
29
30 pub fn get_session_url(&self) -> String {
31 self.build_url("/api/sessions")
32 }
33
34 pub fn build_url(&self, endpoint: &str) -> String {
35 format!("{}{}", self.hostname, endpoint)
36 }
37
38 async fn get_authentication_token(&mut self) -> Result<String> {
39 if let Some(token) = &self.token {
40 return Ok(token.clone());
41 }
42 let login_body = Login::new(self.username.as_str(), self.password.as_str()).to_string();
43
44 let url = self.get_session_url();
45
46 let response = self
47 .client
48 .post(url)
49 .header(CONTENT_TYPE, "application/json")
50 .body(login_body)
51 .send()
52 .await?;
53
54 if !response.status().is_success() {
55 return Err(Error::Runtime("Request failed".to_string()));
56 }
57
58 let token_response: AccessToken = response.json().await?;
59 self.token = Some(token_response.access_token.clone());
60 Ok(token_response.access_token)
61 }
62
63 pub async fn request(&mut self, action: Action) -> Result<Response> {
64 let url = self.build_url(&action.get_url());
65
66 let request = self
67 .client
68 .request(action.get_method(), url)
69 .bearer_auth(self.get_authentication_token().await?);
70
71 let request = if let Some(body) = action.get_body() {
72 request
73 .body(body)
74 .header(CONTENT_TYPE, action.get_content_type().unwrap())
75 } else {
76 request
77 };
78 request.send().await.map_err(Error::Reqwest)
79 }
80
81 pub async fn request_and_parse<T>(&mut self, action: Action) -> Result<T>
82 where
83 T: for<'de> serde::Deserialize<'de>,
84 {
85 let response = self.request(action).await?;
86 let result = response.json::<T>().await?;
87 Ok(result)
88 }
89}