1use json::{object, JsonValue};
2use log::debug;
3use reqwest::blocking::multipart::{Form, Part};
4use reqwest::Method as OtherMethod;
5use serde_json::Value;
6use std::collections::HashMap;
7use std::fmt::Debug;
8use std::{fs, str};
9
10#[derive(Debug)]
11pub struct Http {
12 pub url: String,
13 method: Method,
14 header: HashMap<String, String>,
15 debug: bool,
16 read_timeout: u64,
17 write_timeout: u64,
18 pub query: String,
19
20 content_type: ContentType,
21 param_form_data: Option<Form>,
22 param_form_urlencoded: HashMap<String, String>,
23 param_raw_json: JsonValue,
24 param_raw_text: String,
25 param_raw_stream: Vec<u8>,
26 status: u16,
27 response_header: HashMap<String, String>,
28 response_cookie: HashMap<String, String>,
29
30}
31
32impl Default for Http {
33 fn default() -> Self {
34 Self::new()
35 }
36}
37
38impl Http {
39 pub fn new() -> Http {
40 Self {
41 url: "".to_string(),
42 method: Method::new(),
43 header: Default::default(),
44 debug: false,
45 read_timeout: 5,
46 write_timeout: 5,
47 query: "".to_string(),
48 content_type: ContentType::None,
49 param_form_data: None,
50 param_form_urlencoded: Default::default(),
51 param_raw_json: JsonValue::Null,
52 param_raw_text: "".to_string(),
53 param_raw_stream: vec![],
54 status: 0,
55 response_header: Default::default(),
56 response_cookie: Default::default(),
57 }
58 }
59 pub fn set_read_timeout(&mut self, secs: u64) -> &mut Self {
60 self.read_timeout = secs;
61 self
62 }
63 pub fn set_write_timeout(&mut self, secs: u64) -> &mut Self {
64 self.write_timeout = secs;
65 self
66 }
67 pub fn debug(&mut self, open: bool) -> &mut Self {
69 self.debug = open;
70 self
71 }
72 pub fn get(&mut self, url: &str) -> &mut Self {
74 self.url = url.to_string();
75 self.method = Method::GET;
76 self
77 }
78 pub fn post(&mut self, url: &str) -> &mut Http {
80 self.url = url.to_string();
81 self.method = Method::POST;
82 self
83 }
84 pub fn options(&mut self, url: &str) -> &mut Http {
85 self.url = url.to_string();
86 self.method = Method::OPTIONS;
87 self
88 }
89 pub fn put(&mut self, url: &str) -> &mut Http {
90 self.url = url.to_string();
91 self.method = Method::PUT;
92 self
93 }
94 pub fn patch(&mut self, url: &str) -> &mut Http {
95 self.url = url.to_string();
96 self.method = Method::PATCH;
97 self
98 }
99 pub fn head(&mut self, url: &str) -> &mut Http {
100 self.url = url.to_string();
101 self.method = Method::HEAD;
102 self
103 }
104 pub fn delete(&mut self, url: &str) -> &mut Http {
105 self.url = url.to_string();
106 self.method = Method::DELETE;
107 self
108 }
109 pub fn header(&mut self, key: &str, value: &str) -> &mut Http {
110 self.header.insert(key.to_string(), value.to_string());
111 self
112 }
113 pub fn bearer_auth(&mut self, token: &str) -> &mut Http {
115 self.header.insert("Authorization".to_string(), format!("Bearer {}", token));
116 self
117 }
118 pub fn cookie(&mut self, key: &str, value: &str) -> &mut Http {
119 self.header.insert("Cookie".to_string(), format!("{}={}", key, value));
120 self
121 }
122 pub fn query(&mut self, mut data: JsonValue) -> &mut Self {
124 let mut t = vec![];
125 for (key, value) in data.entries_mut() {
126 t.push(format!("{}={}", key, value))
127 }
128 self.query = t.join("&");
129 if !self.query.is_empty() && !self.url.contains("?") {
130 self.url = format!("{}?{}", self.url, self.query);
131 }
132 self
133 }
134 pub fn form_data(&mut self, data: Vec<FormData>) -> &mut Self {
136 self.content_type = ContentType::FormData;
137
138 let mut form = Form::new();
139 for item in data {
140 match item {
141 FormData::Text(key, value, mime) => {
142 let r = if !mime.is_empty() {
143 Part::text(value.to_string()).mime_str(mime.clone().as_str())
144 } else {
145 Ok(Part::text(value.to_string()))
146 };
147 form = form.part(key, r.unwrap());
148 }
149 FormData::File(key, path, mime) => {
150 let r = if !mime.is_empty() {
151 Part::bytes(fs::read(path).unwrap()).file_name(key.to_string()).mime_str(mime.clone().as_str())
152 } else {
153 Ok(Part::bytes(fs::read(path).unwrap()).file_name(key.to_string()))
154 };
155 form = form.part(key, r.unwrap());
156 }
157 FormData::None => {}
158 }
159 }
160 self.param_form_data = Some(form);
161 self
162 }
163 pub fn form_urlencoded(&mut self, data: JsonValue) -> &mut Self {
165 self.content_type = ContentType::FormUrlencoded;
166 let mut params = HashMap::new();
167 for (key, value) in data.entries() {
168 params.insert(key.to_string(), value.to_string());
169 }
170 self.param_form_urlencoded = params;
171 self
172 }
173 pub fn raw_json(&mut self, data: JsonValue) -> &mut Self {
175 self.header("Content-Type", ContentType::Json.str().as_str());
176 self.content_type = ContentType::Json;
177 if !data.is_empty() {
178 self.param_raw_json = data;
179 }
180 self
181 }
182 pub fn raw_javascript(&mut self, data: &str) -> &mut Self {
183 self.header("Content-Type", ContentType::Javascript.str().as_str());
184 self.content_type = ContentType::Javascript;
185 self.param_raw_text = data.to_string();
186 self
187 }
188 pub fn raw_xml(&mut self, data: &str) -> &mut Self {
189 self.header("Content-Type", ContentType::Xml.str().as_str());
190 self.content_type = ContentType::Xml;
191 self.param_raw_text = data.to_string();
192 self
193 }
194 pub fn raw_html(&mut self, data: &str) -> &mut Self {
195 self.header("Content-Type", ContentType::Html.str().as_str());
196 self.content_type = ContentType::Html;
197 self.param_raw_text = data.to_string();
198 self
199 }
200 pub fn raw_text(&mut self, data: &str) -> &mut Self {
201 self.header("Content-Type", ContentType::Plain.str().as_str());
202 self.content_type = ContentType::Plain;
203 self.param_raw_text = data.to_string();
204 self
205 }
206 pub fn raw_stream(&mut self, data: Vec<u8>) -> &mut Self {
207 self.header("Content-Type", ContentType::Stream.str().as_str());
208 self.content_type = ContentType::Stream;
209 self.header("Content-Length", data.len().to_string().leak());
210 self.param_raw_stream = data;
211 self
212 }
213 pub fn raw_binary(&mut self, data: Vec<u8>, content_type: &str) -> &mut Self {
214 self.header("Content-Type", content_type);
215 self.content_type = ContentType::Stream;
216 self.header("Content-Length", data.len().to_string().leak());
217 self.param_raw_stream = data;
218 self
219 }
220 fn send(&mut self, mode: &str) -> Result<Vec<u8>, String> {
221 let client = reqwest::blocking::Client::new();
222 let mut request = match self.method {
223 Method::GET => client.get(self.url.as_str()),
224 Method::POST => client.post(self.url.as_str()),
225 Method::OPTIONS => client.request(OtherMethod::OPTIONS, self.url.as_str()),
226 Method::PATCH => client.patch(self.url.as_str()),
227 Method::HEAD => client.head(self.url.as_str()),
228 Method::DELETE => client.delete(self.url.as_str()),
229 Method::PUT => client.put(self.url.as_str()),
230 Method::TRACE => client.request(OtherMethod::TRACE, self.url.as_str()),
231 Method::NONE => client.request(OtherMethod::CONNECT, self.url.as_str()),
232 };
233
234 match self.content_type {
235 ContentType::FormData => {
236 request = request.multipart(self.param_form_data.take().unwrap());
237 }
238 ContentType::FormUrlencoded => {
239 request = request.form(&self.param_form_urlencoded);
240 }
241 ContentType::Json => {
242 let body = self.param_raw_json.dump();
243 request = request.body(body.as_bytes().to_vec());
244 }
245 ContentType::Xml | ContentType::Plain | ContentType::Html | ContentType::Javascript => {
246 let body = self.param_raw_text.as_mut_str();
247 request = request.body(body.as_bytes().to_vec());
248 }
249 ContentType::Stream => {
250 request = request.body(self.param_raw_stream.clone());
251 }
252 ContentType::None => {
253 let body = self.param_raw_text.as_mut_str();
254 request = request.body(body.as_bytes().to_vec());
255 }
256 }
257
258 for (key, value) in self.header.iter() {
259 request = request.header(key.clone(), value.clone());
260 }
261
262 if self.debug {
263 debug!("发送数据: {:#?}", request.try_clone().unwrap());
264 }
265 match request.send() {
266 Ok(e) => {
267 if self.debug {
268 debug!("返回数据: {:#?}", e);
269 }
270 self.status = e.status().as_u16();
271 self.response_header = HashMap::new();
272 for (key, value) in e.headers().clone() {
273 if key.clone().is_some() {
274 self.response_header.insert(
275 key.unwrap().to_string(),
276 value.to_str().unwrap().trim_start_matches("\"").trim_end_matches("\"").to_string(),
277 );
278 }
279 }
280 self.response_cookie = HashMap::new();
281 let cookies = e.cookies().collect::<Vec<_>>();
282 for cookie in cookies.iter() {
283 self.response_cookie.insert(cookie.name().to_string(), cookie.value().to_string());
284 }
285
286 match mode {
287 "json" => {
288 let r = e.json::<Value>();
289 match r {
290 Ok(e) => Ok(e.to_string().as_bytes().to_vec()),
291 Err(_e) => Ok("".to_string().as_bytes().to_vec()),
292 }
293 }
294 "html" => {
295 let r = e.text();
296 match r {
297 Ok(e) => Ok(e.as_bytes().to_vec()),
298 Err(e) => Err(e.to_string()),
299 }
300 }
301 "stream" => {
302 let r = e.bytes().unwrap().to_vec();
303 Ok(r)
304 }
305 "info" => {
306 let r = e.text();
307 match r {
308 Ok(e) => Ok(e.as_bytes().to_vec()),
309 Err(e) => Err(e.to_string()),
310 }
311 }
312 &_ => Ok(vec![]),
313 }
314 }
315 Err(e) => Err(e.to_string()),
316 }
317 }
318 pub fn html(&mut self) -> Result<String, String> {
320 match self.send("html") {
321 Ok(e) => {
322 let res = unsafe { String::from_utf8_unchecked(e) };
323 Ok(res)
324 }
325 Err(e) => Err(e),
326 }
327 }
328 pub fn json(&mut self) -> Result<JsonValue, String> {
330 match self.send("json") {
331 Ok(e) => {
332 let res = unsafe { String::from_utf8_unchecked(e) };
333 Ok(json::parse(&res).unwrap_or(object! {}))
334 }
335 Err(e) => Err(e),
336 }
337 }
338 #[allow(clippy::type_complexity)]
339 pub fn info(&mut self) -> Result<(u16, String, HashMap<String, String>, HashMap<String, String>), String> {
341 match self.send("info") {
342 Ok(e) => {
343 let res = unsafe { String::from_utf8_unchecked(e) };
344 Ok((
345 self.status,
346 res,
347 self.response_header.clone(),
348 self.response_cookie.clone()
349 ))
350 }
351 Err(e) => Err(e),
352 }
353 }
354
355 pub fn stream(&mut self) -> Result<Vec<u8>, String> {
356 match self.send("stream") {
357 Ok(e) => Ok(e),
358 Err(e) => Err(e),
359 }
360 }
361}
362
363#[derive(Clone, Debug)]
364pub enum Method {
365 GET,
366 POST,
367 OPTIONS,
368 PATCH,
369 HEAD,
370 DELETE,
371 TRACE,
372 PUT,
373 NONE,
374}
375
376impl Method {
377 fn new() -> Self {
378 Method::GET
379 }
380 pub fn to_str(&self) -> String {
381 match self {
382 Method::GET => "GET",
383 Method::POST => "POST",
384 Method::OPTIONS => "OPTIONS",
385 Method::PATCH => "PATCH",
386 Method::HEAD => "HEAD",
387 Method::DELETE => "DELETE",
388 Method::TRACE => "TRACE",
389 Method::PUT => "PUT",
390 Method::NONE => "NONE",
391 }.to_string()
392 }
393}
394#[derive(Clone, Debug)]
395pub enum Version {
396 Http09,
397 Http10,
398 Http11,
399 H2,
400 H3,
401 None,
402}
403
404impl Version {
405 pub fn str(&mut self) -> String {
406 match self {
407 Version::Http09 => "HTTP/0.9",
408 Version::Http10 => "HTTP/1.0",
409 Version::Http11 => "HTTP/1.1",
410 Version::H2 => "HTTP/2.0",
411 Version::H3 => "HTTP/3.0",
412 Version::None => "",
413 }.to_string()
414 }
415 pub fn from(name: &str) -> Version {
416 match name {
417 "HTTP/0.9" => Self::Http09,
418 "HTTP/1.0" => Self::Http10,
419 "HTTP/1.1" => Self::Http11,
420 "HTTP/2.0" => Self::H2,
421 "HTTP/3.0" => Self::H3,
422 _ => Self::None,
423 }
424 }
425 pub fn set_version(name: &str) -> Version {
426 match name {
427 "0.9" => Self::Http09,
428 "1.0" => Self::Http10,
429 "1.1" => Self::Http11,
430 "2.0" => Self::H2,
431 "3.0" => Self::H3,
432 _ => Self::None,
433 }
434 }
435}
436
437#[derive(Clone, Debug)]
439pub enum Body {
440 Json(JsonValue),
441 Text(String),
442 Xml(String),
443 FormData(Vec<u8>),
444 XWwwFormUrlencoded(String),
445 None,
446}
447
448impl Default for Body {
449 fn default() -> Self {
450 Self::new()
451 }
452}
453
454impl Body {
455 pub fn new() -> Body {
456 Self::None
457 }
458 pub fn bytes(&mut self) -> Vec<u8> {
459 match self {
460 Body::Json(e) => e.to_string().as_bytes().to_vec(),
461 Body::Text(e) => e.clone().as_bytes().to_vec(),
462 Body::Xml(e) => e.clone().as_bytes().to_vec(),
463 Body::FormData(e) => e.to_vec().clone(),
464 Body::XWwwFormUrlencoded(e) => e.clone().as_bytes().to_vec(),
465 Body::None => "".as_bytes().to_vec(),
466 }
467 }
468}
469
470#[derive(Clone, Debug)]
471pub enum ContentType {
472 FormData,
473 FormUrlencoded,
474 Json,
475 Xml,
476 Plain,
477 Html,
478 Stream,
479 Javascript,
480 None,
481}
482impl ContentType {
483 pub fn str(&mut self) -> String {
484 match self {
485 ContentType::Plain => "text/plain",
486 ContentType::Html => "text/html",
487 ContentType::Stream => "application/octet-stream",
488 ContentType::Javascript => "application/javascript",
489 ContentType::FormData => "multipart/form-data",
490 ContentType::Json => "application/json",
491 ContentType::Xml => "application/xml",
492 ContentType::None => "",
493 ContentType::FormUrlencoded => "application/x-www-form-urlencoded",
494 }.to_string()
495 }
496 pub fn from(name: &str) -> Self {
497 match name {
498 "application/xml" => ContentType::Xml,
499 "text/plain" => ContentType::Plain,
500 "text/html" => ContentType::Html,
501 "application/octet-stream" => ContentType::Stream,
502 "application/javascript" => ContentType::Javascript,
503 "multipart/form-data" => ContentType::FormData,
504 "application/json" => ContentType::Json,
505 "application/x-www-form-urlencoded" => ContentType::FormUrlencoded,
506 _ => ContentType::None,
507 }
508 }
509}
510#[derive(Clone, Debug)]
511pub enum FormData {
512 Text(String, JsonValue, String),
516 File(String, String, String),
520 None,
521}