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
11pub 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
19pub 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#[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 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 pub serial_no: String,
378 pub effective_time: String,
380 pub expire_time: String,
382 pub public_key: Vec<u8>,
384 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}