1use std::default::Default;
2use std::time::Duration;
3
4use reqwest::Method;
5use serde_json::Value;
6
7use crate::utils;
8
9pub static mut PASSWORD_SHA2: String = String::new();
10
11pub struct Options {
12 pub method: Method,
13 pub body: String,
14 pub timeout: Duration,
15}
16
17impl Default for Options {
18 fn default() -> Self {
19 Options {
20 method: Method::GET,
21 body: String::new(),
22 timeout: Duration::from_secs(6),
23 }
24 }
25}
26
27pub async fn fetch(url: String, options: Options) -> anyhow::Result<Value> {
28 let client = reqwest::Client::new();
29
30 let password_sha2;
31 unsafe { password_sha2 = PASSWORD_SHA2.as_str().to_string() }
32
33 let response = client
34 .request(options.method, url)
35 .header("Auth-Password-SHA2", password_sha2)
36 .body(options.body)
37 .timeout(options.timeout)
38 .send()
39 .await?;
40 if !response.status().is_success() {
41 let err = response.text().await?;
42 return Err(anyhow::anyhow!(err));
43 }
44
45 let body = response.text().await?;
46 let v: Value = serde_json::from_str(&body)?;
47 if v["error"] != "" {
48 return Err(anyhow::anyhow!(v["error"].as_str().unwrap().to_string()));
49 }
50
51 Ok(v["data"].to_owned())
52}
53
54pub async fn fetch_show_json(url: String, options: Options) {
55 match fetch(url, options).await {
56 Ok(result) => {
57 utils::show_json(result);
58 }
59 Err(err) => {
60 println!("Error: {}", err)
61 }
62 }
63}
64
65pub async fn fetch_show_ok(url: String, options: Options) {
66 match fetch(url, options).await {
67 Ok(_) => {
68 println!("Ok")
69 }
70 Err(err) => {
71 println!("Error: {}", err)
72 }
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79 use serde_json::json;
80
81 #[tokio::test]
82 async fn it_fetch_ok() {
83 let mut server = mockito::Server::new_async().await;
84 let url = server.url();
85
86 let body = json!({"data": {"hello":"world"}, "error": ""}).to_string();
87
88 server
89 .mock("GET", "/hello")
90 .with_status(200)
91 .with_body(body)
92 .create_async()
93 .await;
94
95 let result = fetch(format!("{}{}", url, "/hello"), Options::default())
96 .await
97 .unwrap();
98
99 assert_eq!("{\"hello\":\"world\"}", result.to_string());
100 }
101
102 #[tokio::test]
103 async fn it_fetch_status_failed() {
104 let mut server = mockito::Server::new_async().await;
105 let url = server.url();
106
107 let body = "404 page not found";
108
109 server
110 .mock("GET", "/")
111 .with_status(404)
112 .with_body(body)
113 .create_async()
114 .await;
115
116 let result = fetch(format!("{}{}", url, "/"), Options::default())
117 .await
118 .unwrap_err();
119
120 assert_eq!(body, result.to_string());
121 }
122
123 #[tokio::test]
124 async fn it_fetch_error() {
125 let mut server = mockito::Server::new_async().await;
126 let url = server.url();
127
128 let body = json!({"data": null, "error": "`id` not found!"}).to_string();
129
130 server
131 .mock("POST", "/job")
132 .with_status(200)
133 .with_body(body)
134 .create_async()
135 .await;
136
137 let result = fetch(
138 format!("{}{}", url, "/job"),
139 Options {
140 method: Method::POST,
141 ..Default::default()
142 },
143 )
144 .await
145 .unwrap_err();
146
147 assert_eq!("`id` not found!", result.to_string());
148 }
149}