1use std::fs::File;
2use std::time::Duration;
3use curl::easy::{Easy, List};
4use json::{JsonValue, object};
5use std::io::{Read, Write};
6use std::str;
7use log::info;
8
9pub struct Http {
10 url: String,
11 curl: Easy,
12 body: String,
13 headers: Vec<String>,
14 cookies: Vec<String>,
15 pub res_headers: JsonValue,
16 filepath: String,
17 pub res_cookies: JsonValue,
18}
19
20impl Http {
21 pub fn url(url: &str) -> Self {
23 Self {
24 url: url.to_string(),
25 curl: Easy::new(),
26 body: String::new(),
27 headers: Vec::new(),
28 cookies: Vec::new(),
29 res_headers: object! {},
30 filepath: String::new(),
31 res_cookies: object! {},
32 }
33 }
34 pub fn authorization_bearer(&mut self, token: &str) -> &mut Self {
36 self.set_headers("Authorization", format!("Bearer {}", token).as_str());
37 self
38 }
39 pub fn debug(&mut self, open: bool) -> &mut Self {
42 self.curl.verbose(open).unwrap();
43 self
44 }
45 pub fn progress(&mut self, open: bool) -> &mut Self {
47 self.curl.progress(open).unwrap();
48 let mut i = 0.0;
49 self.curl.progress_function(move |total_download_bytes, cur_download_bytes, _total_upload_bytes, _cur_upload_bytes| {
50 if total_download_bytes > 0.0 {
51 if i != cur_download_bytes / total_download_bytes * 100.0 {
52 i = cur_download_bytes / total_download_bytes * 100.0;
53 println!("已下载:{}%", i);
54 }
55 } else {
56 if i > 0.0 {} else {
57 i = 1.0;
58 println!("已下载:0%");
59 }
60 }
61 true
62 }).expect("进度执行失败");
63 self
64 }
65 pub fn set_headers(&mut self, key: &str, value: &str) -> &mut Self {
67 self.headers.push(format!("{}:{}", key, value));
68 self
69 }
70 pub fn set_cookies(&mut self, key: &str, value: &str) -> &mut Self {
72 self.cookies.push(format!("{}={}", key, value));
73 self
74 }
75 pub fn auth(&mut self, username: &str, password: &str) -> &mut Self {
77 self.curl.username(username).unwrap();
78 self.curl.password(password).unwrap();
79 self
80 }
81
82 pub fn post(&mut self, data: JsonValue) -> &mut Self {
84 self.body = data.dump();
85 self.curl.post(true).unwrap();
86 self.curl.post_field_size(self.body.as_bytes().len() as u64).unwrap();
87 self
88 }
89
90 pub fn post_form(&mut self, data: JsonValue) -> &mut Self {
92 self.set_headers("content-type", "application/x-www-form-urlencoded");
93 self.body = data.dump();
94 self.curl.post(true).unwrap();
95 self.curl.post_field_size(self.body.as_bytes().len() as u64).unwrap();
96 self
97 }
98 pub fn post_json(&mut self, data: JsonValue) -> &mut Self {
100 self.set_headers("content-type", "application/json");
101 self.body = data.dump();
102 self.curl.post(true).unwrap();
103 self.curl.post_field_size(self.body.as_bytes().len() as u64).unwrap();
104
105 self
106 }
107 pub fn patch(&mut self, body: JsonValue) -> &mut Self {
109 self.curl.custom_request("PATCH").unwrap();
110 self.set_headers("content-type", "application/json");
111 self.body = body.dump();
112 self.curl.post_field_size(self.body.as_bytes().len() as u64).unwrap();
113 self
114 }
115
116 pub fn get(&mut self, data: JsonValue) -> &mut Self {
118 self.curl.get(true).unwrap();
119 if !data.is_empty() {
120 let mut url = "".to_string();
121 for (k, v) in data.entries() {
122 if url == "" {
123 url = format!("{}={}", k, v);
124 } else {
125 url = format!("{}&{}={}", url, k, v);
126 }
127 }
128 self.url = format!("{}?{}", self.url, url);
129 }
130 self
131 }
132 pub fn download(&mut self, filepath: &str) -> &mut Self {
134 self.filepath = filepath.to_string();
135 self
136 }
137 pub fn response(&mut self) -> JsonValue {
139 let mut headers = List::new();
140 for header in self.headers.clone() {
141 headers.append(header.as_str()).unwrap();
142 }
143 if !self.headers.is_empty() {
144 self.curl.http_headers(headers).unwrap();
145 }
146 let mut cookies = "".to_string();
147 for cookie in self.cookies.clone() {
148 if cookies == "" {
149 cookies = format!("{}", cookie);
150 } else {
151 cookies = format!("{};{}", cookies, cookie);
152 }
153 }
154 if !self.cookies.is_empty() {
155 self.curl.cookie(&*cookies).unwrap();
156 }
157
158
159 self.curl.accept_encoding("zlib,gzip,identity").unwrap();
161 self.curl.timeout(Duration::from_micros(5)).unwrap();
162 self.curl.connect_timeout(Duration::from_micros(5)).unwrap();
163
164 self.curl.url(self.url.as_str()).unwrap();
165
166 let mut body = Vec::new();
167 {
168 let mut transfer = self.curl.transfer();
169
170 transfer.header_function(|data| {
171 let str = str::from_utf8(data).unwrap();
172 let data: Vec<&str> = str.split(":").collect();
173 let key = data[0].to_lowercase();
174 match key.as_str() {
175 "set-cookie" => {
176 let kv: Vec<&str> = data[1].split(";").collect();
177 let cookie = kv[0].trim();
178 let kv: Vec<&str> = cookie.split("=").collect();
179 for index in 0..kv.len() {
180 let k = kv[0].clone();
181 if index == 0 {
182 self.res_cookies[k] = "".into();
183 } else {
184 if kv[index] == "" {
185 self.res_cookies[k] = format!("{}=", self.res_cookies[k]).into();
186 } else {
187 self.res_cookies[k] = format!("{}", kv[index]).into();
188 }
189 }
190 }
191 }
192 _ => {}
193 }
194 true
195 }).unwrap();
196
197 transfer.read_function(|data| {
198 Ok(self.body.as_bytes().read(data).unwrap())
199 }).unwrap();
200
201 transfer.write_function(|data| {
202 body.extend_from_slice(data.clone());
203 Ok(data.len())
204 }).unwrap();
205
206 transfer.perform().unwrap();
207 }
208 self._state();
209 let data = String::from_utf8_lossy(&body);
210 let data = &data as &str;
211 match self.res_headers["type"].as_str().unwrap() {
212 "json" => {
213 return json::parse(data).unwrap();
214 }
215 "text" => {
216 return JsonValue::from(data);
217 }
218 "jpeg" => {
219 df_file::create_dir(self.filepath.as_str());
220 let mut file = File::create(self.filepath.as_str()).unwrap();
221 file.write(&body).unwrap();
222 let res = df_file::is_file(self.filepath.as_str());
223 return JsonValue::Boolean(res);
224 }
225 _ => {
226 println!("{:#}", self.res_headers);
227 }
228 }
229 return object! {};
230 }
231 fn _state(&mut self) {
233 self.res_headers["code"] = self.curl.response_code().unwrap().into();
234 self.res_headers["content-type"] = self.curl.content_type().unwrap().into();
235 let content_type = self.res_headers["content-type"].to_string();
236 let data: Vec<&str> = content_type.split(";").collect();
237 match data[0] {
238 "application/json" => {
239 self.res_headers["type"] = "json".into();
240 }
241 "text/html" => {
242 self.res_headers["type"] = "text".into();
243 }
244 "image/jpeg" => {
245 self.res_headers["type"] = "jpeg".into();
246 }
247 _ => {
248 info!("{:#?}", data);
249 self.res_headers["type"] = "text".into();
250 }
251 }
252 }
253}