1use core::panic;
10use reqwest::{blocking::Client, Method, Result};
11
12pub const R_OK: &str = "OK";
13pub const R_TRUE: &str = "YES";
14const R_PONG: &str = "PONG";
15const R_INVALID_CREDENTIALS: &str = "INVALID_CREDENTIALS";
16const R_AUTH_FAILED: &str = "AUTH_FAILED";
17
18pub struct HyperClient {
19 address: String,
20 username: String,
21 password: String,
22 auth_enabled: bool,
23 token: String,
24 client: Option<Client>,
25}
26
27impl HyperClient {
28 pub fn new(address: String) -> HyperClient {
29 let mut hc = HyperClient {
30 address,
31 username: String::from(""),
32 password: String::from(""),
33 auth_enabled: false,
34 token: String::from(""),
35 client: None,
36 };
37
38 hc.connect();
39
40 hc
41 }
42
43 #[allow(dead_code)]
44 pub fn authenticate(&mut self, username: String, password: String) {
45 self.username = username;
46 self.password = password;
47 self.auth_enabled = true;
48 self.auth().expect("Authentication failed");
49 }
50
51 fn client(&self) -> Client {
52 match &self.client {
53 Some(c) => c.to_owned(),
54 None => Client::new(),
55 }
56 }
57
58 fn auth(&mut self) -> Result<String> {
59 let client = Client::new();
60 let resp = client
61 .post(&self.address)
62 .header("username", &self.username)
63 .header("password", &self.password)
64 .send()?
65 .text()?;
66
67 if resp == R_INVALID_CREDENTIALS {
68 panic!("Invalid credentials.");
69 }
70
71 self.token = resp.trim().to_string();
72
73 Ok(resp)
74 }
75
76 pub fn connect(&mut self) {
77 let r = self.http(Method::GET, &format!("ping"), "");
78
79 match r {
80 Err(e) => panic!("Unable to connect to the HyperDB server (E_001): {}", e),
81 Ok(r) => {
82 if r != R_PONG {
83 panic!("Unable to connect to the HyperDB server (E_002).")
84 }
85
86 println!("Connected to {}", self.address);
87 }
88 }
89 }
90
91 pub fn ping(&self) -> Result<String> {
92 self.client()
93 .get(String::from(&self.address) + "/ping")
94 .send()?
95 .text()
96 }
97
98 pub fn http(&mut self, method: Method, url: &String, body: &str) -> Result<String> {
99 let m = method.clone();
100
101 let mut r = self
102 .client()
103 .request(method, format!("{}/{}", &self.address, url))
104 .header("Auth", &self.token)
105 .body(body.to_string())
106 .send()?
107 .text()?;
108
109 if r == R_AUTH_FAILED && self.auth_enabled {
110 self.auth()?;
111 r = self
112 .client()
113 .request(m, format!("{}/{}", &self.address, url))
114 .header("Auth", &self.token)
115 .body(body.to_string())
116 .send()?
117 .text()?;
118 }
119
120 Ok(r)
121 }
122
123 pub fn version(&mut self) -> Result<String> {
124 self.http(Method::GET, &format!(""), "")
125 }
126
127 pub fn has(&mut self, key: &str) -> Result<String> {
128 self.http(Method::GET, &format!("has/{}", key), "")
129 }
130
131 pub fn get(&mut self, key: &str) -> Result<String> {
132 self.http(Method::GET, &format!("data/{}", key), "")
133 }
134
135 pub fn set(&mut self, key: &str, value: &str) -> Result<String> {
136 self.http(Method::POST, &format!("data/{}", key), value)
137 }
138
139 pub fn delete(&mut self, key: &str) -> Result<String> {
140 self.http(Method::DELETE, &format!("data/{}", key), "")
141 }
142
143 pub fn all(&mut self) -> Result<String> {
144 self.http(Method::GET, &format!("data"), "")
145 }
146
147 pub fn clear(&mut self) -> Result<String> {
148 self.http(Method::DELETE, &format!("data"), "")
149 }
150
151 pub fn empty(&mut self) -> Result<String> {
152 self.http(Method::GET, &format!("empty"), "")
153 }
154
155 pub fn save(&mut self) -> Result<String> {
156 self.http(Method::POST, &format!("save"), "")
157 }
158
159 pub fn reload(&mut self) -> Result<String> {
160 self.http(Method::POST, &format!("reload"), "")
161 }
162
163 pub fn reset(&mut self) -> Result<String> {
164 self.http(Method::DELETE, &format!("reset"), "")
165 }
166}