br_http/
lib.rs

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    /// 调试
68    pub fn debug(&mut self, open: bool) -> &mut Self {
69        self.debug = open;
70        self
71    }
72    /// GET请求
73    pub fn get(&mut self, url: &str) -> &mut Self {
74        self.url = url.to_string();
75        self.method = Method::GET;
76        self
77    }
78    /// POST请求
79    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    /// bearer 登陆头
114    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    /// query 请求地址参数
123    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    /// form-data 数据类型
135    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    /// form-urlencoded 数据类型
164    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    /// json 数据类型
174    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    /// 返回 html
319    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    /// 返回 JSON
329    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    /// 返回 info
340    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/// 请求
438#[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    /// KEY
513    /// value
514    /// 文本类型
515    Text(String, JsonValue, String),
516    /// 文件名
517    /// 文件路径
518    /// 文件类型
519    File(String, String, String),
520    None,
521}