labrador/
request.rs

1use std::net::SocketAddr;
2use bytes::Bytes;
3use reqwest::{self, multipart, StatusCode, Url};
4use reqwest::header::{HeaderMap, HeaderValue};
5use serde::de::DeserializeOwned;
6use serde::Serialize;
7use crate::errors::LabraError;
8use crate::LabradorResult;
9
10
11/// Parse Data For Response
12pub trait Response <T> where T: Serialize {
13    fn parse_result(&self) -> LabradorResult<T>;
14}
15
16const APP_USER_AGENT: &str = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36";
17
18
19/// Common Params Format
20/// If custom paramters.
21pub trait Params{
22    fn get_params(&self) -> Vec<(String, String)>;
23
24    fn build_biz_content(&self) -> String where Self: Serialize {
25        serde_json::to_string(&self).unwrap_or_default()
26    }
27}
28
29pub trait RequestMethod {
30    fn get_method(&self) -> String ;
31
32    fn get_response_key(&self) -> String {
33        String::default()
34    }
35}
36
37#[allow(unused)]
38#[derive(Debug, PartialEq, Clone)]
39pub enum Method {
40    Options,
41    Get,
42    Post,
43    Put,
44    Delete,
45    Head,
46    Trace,
47    Connect,
48    Patch,
49}
50
51impl From<Method> for reqwest::Method {
52    fn from(m: Method) -> Self {
53        match m {
54            Method::Get => reqwest::Method::GET,
55            Method::Post => reqwest::Method::POST,
56            Method::Options => reqwest::Method::OPTIONS,
57            Method::Put => reqwest::Method::PUT,
58            Method::Delete => reqwest::Method::DELETE,
59            Method::Head => reqwest::Method::HEAD,
60            Method::Trace => reqwest::Method::TRACE,
61            Method::Connect => reqwest::Method::CONNECT,
62            Method::Patch => reqwest::Method::PATCH,
63        }
64    }
65}
66
67impl ToString for Method {
68    fn to_string(&self) -> String {
69        match self {
70            Method::Options => String::from("OPTIONS"),
71            Method::Get => String::from("GET"),
72            Method::Post => String::from("POST"),
73            Method::Put => String::from("PUT"),
74            Method::Delete => String::from("DELETE"),
75            Method::Head => String::from("HEAD"),
76            Method::Trace => String::from("TRACE"),
77            Method::Connect => String::from("CONNECT"),
78            Method::Patch => String::from("PATCH"),
79        }
80    }
81}
82
83#[derive(Debug)]
84pub enum RequestBody<T: Serialize> {
85    Json(T),
86    Form(T),
87    Multipart(multipart::Form),
88    Xml(String),
89    Text(String),
90    Raw(Bytes),
91    Null
92}
93
94impl <T: Serialize> RequestBody<T> {
95
96    pub fn to_string(&self) -> String {
97        match self {
98            RequestBody::Json(v) => serde_json::to_string(&v).unwrap_or_default(),
99            RequestBody::Form(v) => serde_json::to_string(&v).unwrap_or_default(),
100            RequestBody::Multipart(v) => {
101                v.boundary().to_string()
102            }
103            RequestBody::Xml(v) => v.to_string(),
104            RequestBody::Text(v) => v.to_string(),
105            RequestBody::Raw(_v) => String::from("bytes"),
106            RequestBody::Null => String::default(),
107        }
108    }
109}
110
111impl <T: Serialize> From<multipart::Form> for RequestBody<T> {
112    fn from(v: multipart::Form) -> Self {
113           RequestBody::Multipart(v)
114    }
115}
116impl <T: Serialize> From<String> for RequestBody<T> {
117    fn from(v: String) -> Self {
118           RequestBody::Text(v)
119    }
120}
121
122impl <T: Serialize> From<&str> for RequestBody<T> {
123    fn from(v: &str) -> Self {
124           RequestBody::Text(v.to_string())
125    }
126}
127
128impl <T: Serialize> From<Bytes> for RequestBody<T> {
129    fn from(v: Bytes) -> Self {
130           RequestBody::Raw(v)
131    }
132}
133
134impl <T: Serialize> From<Vec<u8>> for RequestBody<T> {
135    fn from(vec: Vec<u8>) -> Self {
136        RequestBody::Raw(Bytes::from(vec))
137    }
138}
139
140impl <T: Serialize> From<&'static [u8]> for RequestBody<T> {
141    fn from(s: &'static [u8]) -> Self {
142        RequestBody::Raw(Bytes::from_static(s))
143    }
144}
145
146#[allow(unused)]
147#[derive(Debug, PartialEq, Clone)]
148pub enum RequestType {
149    Json,
150    Form,
151    Multipart,
152    Xml,
153}
154
155/// LabraRequest
156///
157/// # Examples
158///
159/// ```no_run
160/// use labrador::APIClient;
161/// use serde_json::json;
162/// use labrador::Method;
163/// use labrador::{LabraRequest,LabradorResult};
164/// use std::error::Error;
165/// fn main() -> LabradorResult<(), Error> {
166///     let api = APIClient::new("appkey", "secret", "http_url");
167///     let params = vec![(String::from("key"), String::from("value"))];
168///     let data = json!({
169///         "key": "value"
170///     });
171///     let req = LabraRequest::new().method(Method::Post).data(data).req_type(request_type).params(params);
172///     let _ = req.request().await?;
173///     let _ = req.request_blocking().await?;
174/// }
175/// ```
176///
177#[allow(unused)]
178#[derive(Debug)]
179pub struct LabraRequest <T> where T: Serialize {
180    pub url: String,
181    pub method: Method,
182    pub req_type : RequestType,
183    pub identity: Option<LabraIdentity>,
184    pub cert: Option<LabraCertificate>,
185    pub params: Option<Vec<(String, String)>>,
186    pub headers: Option<Vec<(String, String)>>,
187    pub body: RequestBody<T>
188}
189
190#[allow(unused)]
191pub struct LabraResponse {
192    url: Url,
193    status: StatusCode,
194    headers: HeaderMap,
195    remote_addr: Option<SocketAddr>,
196    body: Bytes
197}
198
199impl LabraResponse {
200    fn new(url: Url, status: StatusCode, remote_addr: Option<SocketAddr>, headers: HeaderMap, body: Bytes) -> LabraResponse {
201        LabraResponse {
202            url,
203            headers,
204            remote_addr,
205            status,
206            body
207        }
208    }
209
210    pub fn status(&self) -> StatusCode {
211        self.status
212    }
213
214    pub fn url(&self) -> &Url {
215        &self.url
216    }
217
218    pub fn remote_addr(&self) -> Option<SocketAddr> {
219        self.remote_addr
220    }
221
222    pub fn header(&self) -> &HeaderMap {
223        &self.headers
224    }
225
226    pub fn json<T: DeserializeOwned>(&self) -> LabradorResult<T> {
227        serde_json::from_slice(&self.body).map_err(LabraError::from)
228    }
229
230    pub fn text(&self) -> LabradorResult<String> {
231        unsafe {
232            // decoding returned Cow::Borrowed, meaning these bytes
233            // are already valid utf8
234            Ok(String::from_utf8_unchecked(self.body.to_vec()))
235        }
236    }
237
238    pub fn bytes(&self) -> LabradorResult<Bytes> {
239        Ok(self.body.clone())
240    }
241}
242
243#[allow(unused)]
244impl <T> LabraRequest <T> where T: Serialize {
245    pub fn new() -> Self {
246        LabraRequest { url: String::default(), method: Method::Post, req_type: RequestType::Json, identity: None, cert: None, params: None, headers: None, body: RequestBody::Null }
247    }
248
249    pub fn url(mut self, url: String) -> Self {
250        self.url = url;
251        self
252    }
253
254    pub fn method(mut self, method: Method) -> Self {
255        self.method = method;
256        self
257    }
258
259    pub fn req_type(mut self, req_type: RequestType) -> Self {
260        self.req_type = req_type;
261        self
262    }
263
264    pub fn headers(mut self, headers: Vec<(String, String)>) -> Self {
265        self.headers = headers.into();
266        self
267    }
268
269    pub fn identity(mut self, identity: LabraIdentity) -> Self {
270        self.identity = identity.into();
271        self
272    }
273
274    pub fn cert(mut self, cert: LabraCertificate) -> Self {
275        self.cert = cert.into();
276        self
277    }
278
279    pub fn params(mut self, params: Vec<(String, String)>) -> Self {
280        self.params = params.into();
281        self
282    }
283
284    pub fn body(mut self, body: RequestBody<T>) -> Self {
285        self.body = body.into();
286        self
287    }
288
289    pub fn json(mut self, data: T) -> Self {
290        self.body = RequestBody::Json(data);
291        self
292    }
293
294    pub fn form(mut self, data: T) -> Self {
295        self.body = RequestBody::Form(data);
296        self
297    }
298
299    pub fn multipart_form(mut self, data: multipart::Form) -> Self {
300        self.body = RequestBody::Multipart(data);
301        self
302    }
303
304    pub fn bytes(mut self, bytes: Bytes) -> Self {
305        self.body = bytes.into();
306        self
307    }
308
309    pub fn text(mut self, data: &str) -> Self {
310        self.body = data.into();
311        self
312    }
313
314    #[inline]
315    pub async fn request(self) -> LabradorResult<LabraResponse> {
316        let mut http_url = Url::parse(&self.url).map_err(|e| LabraError::RequestError(e.to_string()))?;
317        if let Some(params) = &self.params {
318            http_url.query_pairs_mut().extend_pairs(params.into_iter());
319        }
320        let mut client = reqwest::Client::builder().user_agent(APP_USER_AGENT);
321        if let Some(identity) = &self.identity {
322            client = client.identity(identity.identity());
323        }
324        if let Some(cert) = &self.cert {
325            client = client.add_root_certificate(cert.reqwest_cert()?);
326        }
327        let client = client.build()?;
328        let mut request = client.request(self.method.clone().into(), http_url.to_owned());
329        let mut data = &self.body.to_string();
330        match self.body {
331            RequestBody::Json(v) => {
332                request = request.json(&v);
333            }
334            RequestBody::Form(v) => {
335                request = request.form(&v);
336            }
337            RequestBody::Multipart(v) => {
338                request = request.multipart(v);
339            }
340            RequestBody::Xml(v) => {
341                request = request.body(v);
342            }
343            RequestBody::Text(v) => {
344                request = request.body(v);
345            }
346            RequestBody::Raw(v) => {
347                request = request.body(v);
348            }
349            RequestBody::Null => {}
350        }
351        if let Some(headers) = &self.headers {
352            for (k, v) in headers.into_iter() {
353                request = request.header(k, HeaderValue::from_str(v)?);
354            }
355        }
356        tracing::info!("[请求第三方接口参数] url: {}, data:{}", http_url.as_str(), data);
357        let result = request.send().await?;
358        let status = result.status();
359        let remote_addr = result.remote_addr();
360        let headers = result.headers();
361        let response = LabraResponse::new(result.url().clone(), status, remote_addr, headers.clone(), result.bytes().await?);
362        tracing::info!("[请求第三方接口响应] data:{}", &response.text().unwrap_or_default());
363        Ok(response)
364    }
365}
366
367
368#[derive(Debug, Clone)]
369pub struct LabraIdentity {
370    identity: reqwest::Identity,
371}
372
373
374#[derive(Debug, Clone)]
375pub struct LabraCertificate {
376    /// 序列号
377    pub serial_no: String,
378    /// 颁发时间
379    pub effective_time: String,
380    /// 过期时间
381    pub expire_time: String,
382    /// PublicKey
383    pub public_key: Vec<u8>,
384    /// 证书
385    pub content: Vec<u8>,
386}
387
388impl LabraIdentity {
389
390    pub fn from_pkcs12_der(der: Vec<u8>, password: &str) -> LabradorResult<Self> {
391        let identity = reqwest::Identity::from_pkcs12_der(&der, password)?;
392        Ok(Self {
393            identity,
394        })
395    }
396
397    pub fn from_pem(der: Vec<u8>) -> LabradorResult<Self> {
398        let identity = reqwest::Identity::from_pem(&der)?;
399        Ok(Self {
400            identity,
401        })
402    }
403
404    pub fn identity(&self) -> reqwest::Identity {
405        self.identity.clone()
406    }
407
408}
409
410impl LabraCertificate {
411
412    #[cfg(not(feature = "openssl-crypto"))]
413    pub fn from_pem(pem: Vec<u8>) -> LabradorResult<Self> {
414        let (_data, x509) = x509_parser::pem::parse_x509_pem(&pem)?;
415        let x509 = x509.parse_x509()?;
416        let pk = x509.public_key();
417        let sn = x509.serial.to_string();
418        let pk_content = base64::encode(pk.raw);
419        Ok(Self {
420            serial_no: sn.to_string(),
421            effective_time: "".to_string(),
422            expire_time: "".to_string(),
423            public_key: pk_content.as_bytes().to_vec(),
424            content: pem,
425        })
426    }
427
428    #[cfg(not(feature = "openssl-crypto"))]
429    pub fn from(pem: &str) -> LabradorResult<Self> {
430        let content = pem.as_bytes();
431        let (_data, x509) = x509_parser::pem::parse_x509_pem(content)?;
432        let cert = x509.parse_x509()?;
433        let pk = cert.public_key();
434        let pk_content = base64::encode(pk.raw);
435        Ok(Self {
436            serial_no: "".to_string(),
437            effective_time: "".to_string(),
438            expire_time: "".to_string(),
439            public_key: pk_content.as_bytes().to_vec(),
440            content: content.to_vec(),
441        })
442    }
443
444    #[cfg(feature = "openssl-crypto")]
445    pub fn from_pem(pem: Vec<u8>) -> LabradorResult<Self> {
446        let x509 = openssl::x509::X509::from_pem(&pem)?;
447        let pk = x509.public_key()?;
448        let rpk = pk.public_key_to_pem()?;
449        let sn = x509.serial_number().to_bn()?.to_string();
450        Ok(Self {
451            serial_no: sn.to_string(),
452            effective_time: "".to_string(),
453            expire_time: "".to_string(),
454            public_key: rpk,
455            content: pem,
456        })
457    }
458
459    #[cfg(feature = "openssl-crypto")]
460    pub fn from(pem: &str) -> LabradorResult<Self> {
461        let content = pem.as_bytes();
462        let x509 = openssl::x509::X509::from_pem(content)?;
463        let pk = x509.public_key()?;
464        let rpk = pk.public_key_to_pem()?;
465        Ok(Self {
466            serial_no: "".to_string(),
467            effective_time: "".to_string(),
468            expire_time: "".to_string(),
469            public_key: rpk,
470            content: content.to_vec(),
471        })
472    }
473
474
475    pub fn reqwest_cert(&self) -> LabradorResult<reqwest::Certificate> {
476        let cert = reqwest::Certificate::from_pem(self.content.as_ref())?;
477        Ok(cert)
478    }
479
480
481    pub fn content(&self) -> LabradorResult<String> {
482        let content = String::from_utf8_lossy(&self.content);
483        Ok(content.to_string())
484    }
485
486}
487
488
489#[allow(unused)]
490impl RequestType {
491    pub fn get_content_type(&self) -> String {
492        match *self {
493            RequestType::Json => String::from("application/json;charset=UTF-8"),
494            RequestType::Form => String::from("application/x-www-form-urlencoded;charset=UTF-8"),
495            RequestType::Multipart => String::from("multipart/form-data;charset=UTF-8"),
496            RequestType::Xml => String::from("application/xml;charset=UTF-8"),
497        }
498    }
499}
500
501pub async fn request<F>(f: F) -> LabradorResult<LabraResponse>
502where
503    F: Fn(reqwest::Client) -> reqwest::RequestBuilder,
504{
505    let result = f(reqwest::Client::new()).send().await?;
506    Ok(LabraResponse::new(result.url().clone(), result.status(), result.remote_addr(), result.headers().clone(), result.bytes().await?))
507}
508
509#[allow(unused)]
510pub fn request_blocking<F>(f: F) -> LabradorResult<LabraResponse>
511where
512    F: Fn(reqwest::blocking::Client) -> reqwest::blocking::RequestBuilder,
513{
514    let result = f(reqwest::blocking::Client::new()).send()?;
515    Ok(LabraResponse::new(result.url().clone(), result.status(), result.remote_addr(), result.headers().clone(), result.bytes()?))
516}