product_os_request/
lib.rs

1#![no_std]
2extern crate no_std_compat as std;
3
4use std::prelude::v1::*;
5
6use async_trait::async_trait;
7use std::collections::BTreeMap;
8use std::str::FromStr;
9use std::time::Duration;
10
11#[cfg(any(feature = "method", feature = "method_std"))]
12use serde::{ Serialize, Deserialize };
13
14#[cfg(any(feature = "request", feature = "response", feature = "request_std", feature = "response_std"))]
15pub use product_os_http::{
16    Request, Response,
17    header::{ HeaderMap, HeaderName, HeaderValue },
18    StatusCode,
19    Uri
20};
21
22#[cfg(any(feature = "request", feature = "response", feature = "request_std", feature = "response_std"))]
23pub use product_os_http_body::*;
24
25
26#[cfg(any(feature = "method", feature = "method_std"))]
27pub use product_os_http::method::Method as HttpMethod;
28
29#[cfg(any(feature = "request", feature = "request_std"))]
30use product_os_http::request;
31
32#[cfg(any(feature = "request", feature = "request_std"))]
33use bytes::Bytes;
34use product_os_http::response::Parts;
35
36#[cfg(any(feature = "request", feature = "request_std"))]
37#[derive(Clone, Debug, PartialEq, Eq)]
38pub enum Protocol {
39    SOCKS5,
40    HTTP,
41    HTTPS,
42    ALL
43}
44
45#[cfg(any(feature = "request", feature = "request_std"))]
46#[derive(Clone, Debug, PartialEq, Eq)]
47pub struct Proxy {
48    pub protocol: Protocol,
49    pub address: String
50}
51
52
53#[cfg(any(feature = "request", feature = "request_std"))]
54#[derive(Clone, Debug, PartialEq, Eq)]
55pub enum RedirectPolicy {
56    None,
57    Limit(usize),
58    Default
59}
60
61#[cfg(any(feature = "method", feature = "method_std"))]
62#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
63pub enum Method {
64    GET,
65    POST,
66    PATCH,
67    PUT,
68    DELETE,
69    TRACE,
70    HEAD,
71    OPTIONS,
72    CONNECT,
73    ANY
74}
75
76#[cfg(any(feature = "method", feature = "method_std"))]
77impl Method {
78    pub fn to_http_method(&self) -> product_os_http::method::Method {
79        match self {
80            Method::GET => product_os_http::method::Method::GET,
81            Method::POST => product_os_http::method::Method::POST,
82            Method::PATCH => product_os_http::method::Method::PATCH,
83            Method::PUT => product_os_http::method::Method::PUT,
84            Method::DELETE => product_os_http::method::Method::DELETE,
85            Method::TRACE => product_os_http::method::Method::TRACE,
86            Method::HEAD => product_os_http::method::Method::HEAD,
87            Method::OPTIONS => product_os_http::method::Method::OPTIONS,
88            Method::CONNECT => product_os_http::method::Method::CONNECT,
89            Method::ANY => product_os_http::method::Method::GET
90        }
91    }
92
93    pub fn from_http_method(method: &product_os_http::Method) -> Self {
94        match method {
95            &product_os_http::method::Method::GET => Method::GET,
96            &product_os_http::method::Method::POST => Method::POST,
97            &product_os_http::method::Method::PATCH => Method::PATCH,
98            &product_os_http::method::Method::PUT => Method::PUT,
99            &product_os_http::method::Method::DELETE => Method::DELETE,
100            &product_os_http::method::Method::TRACE => Method::TRACE,
101            &product_os_http::method::Method::HEAD => Method::HEAD,
102            &product_os_http::method::Method::OPTIONS => Method::OPTIONS,
103            &product_os_http::method::Method::CONNECT => Method::CONNECT,
104            _ => Method::ANY
105        }
106    }
107
108    pub fn from_str(method: &str) -> Self {
109        match method {
110            "GET" => Method::GET,
111            "POST" => Method::POST,
112            "PATCH" => Method::PATCH,
113            "PUT" => Method::PUT,
114            "DELETE" => Method::DELETE,
115            "TRACE" => Method::TRACE,
116            "HEAD" => Method::HEAD,
117            "OPTIONS" => Method::OPTIONS,
118            "CONNECT" => Method::CONNECT,
119            _ => Method::ANY
120        }
121    }
122}
123
124
125
126
127#[cfg(any(feature = "request", feature = "request_std"))]
128pub enum BodyType {
129    Json,
130    Form
131}
132
133
134
135#[cfg(any(feature = "request", feature = "request_std"))]
136#[derive(Debug)]
137pub enum ProductOSRequestError {
138    Error(String),
139    None
140}
141
142#[cfg(any(feature = "request", feature = "request_std"))]
143impl std::fmt::Display for ProductOSRequestError {
144    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
145        match &self {
146            ProductOSRequestError::Error(m) => write!(f, "{}", m),
147            ProductOSRequestError::None => write!(f, "No error")
148        }
149    }
150}
151
152
153#[cfg(any(feature = "request", feature = "request_std"))]
154pub struct ProductOSRequest<DReq> {
155    url: Uri,
156    method: Method,
157
158    headers: BTreeMap<String, HeaderValue>,
159    bearer_auth: Option<String>,
160
161    query: BTreeMap<String, String>,
162
163    body: Option<DReq>,
164
165    content_type: Option<BodyType>,
166}
167
168
169#[cfg(any(feature = "request", feature = "request_std"))]
170impl<DReq: product_os_http_body::Body> ProductOSRequest<DReq> {
171    fn new(method: Method, url: &str) -> Self {
172        let uri = match Uri::from_str(url) {
173            Ok(u) => u,
174            Err(e) => {
175                tracing::error!("Uri is invalid: {:?}", e);
176                Uri::default()
177            }
178        };
179
180        Self {
181            url: uri,
182            method,
183
184            headers: BTreeMap::new(),
185            bearer_auth: None,
186
187            query: BTreeMap::new(),
188
189            body: None,
190
191            content_type: None,
192        }
193    }
194
195    fn from_request(r: Request<DReq>) -> Self {
196        let uri = r.uri().to_owned();
197        let method = Method::from_http_method(r.method());
198
199        let mut headers = BTreeMap::new();
200        let mut bearer_auth = None;
201        let mut content_type = None;
202
203        for (name, value) in r.headers() {
204            let name = name.to_string();
205
206            if name.as_str().to_lowercase() == "authorization" {
207                match value.to_str() {
208                    Ok(val) => { bearer_auth = Some(val.to_string()); }
209                    Err(_) => {}
210                }
211            }
212            else if name.as_str().to_lowercase() == "content-type" {
213                match value.to_str() {
214                    Ok(val) => {
215                        content_type = match val {
216                            "application/json" => Some(BodyType::Json),
217                            "application/www-form-url-encoded" => Some(BodyType::Form),
218                            _ => None
219                        }
220                    }
221                    Err(_) => {}
222                }
223            }
224            else {
225                headers.insert(name.to_string(), value.to_owned());
226            }
227        }
228
229        let query = match uri.query() {
230            None => BTreeMap::new(),
231            Some(query) => {
232                let mut query_tree = BTreeMap::new();
233
234                let query_parts = query.split("&").collect::<Vec<&str>>();
235                for query_part in query_parts {
236                    let query_sub_parts = query_part.split("=").collect::<Vec<&str>>();
237                    match query_sub_parts.get(0) {
238                        None => {}
239                        Some(key) => {
240                            match query_sub_parts.get(1) {
241                                None => {}
242                                Some(value) => { query_tree.insert(key.to_string(), value.to_string()); }
243                            }
244                        }
245                    }
246                }
247
248                query_tree
249            }
250        };
251
252        let body = r.into_body();
253
254        Self {
255            url: uri,
256            method,
257
258            headers,
259            bearer_auth,
260
261            query,
262
263            body: Some(body),
264
265            content_type
266        }
267    }
268
269    pub fn add_header(&mut self, name: &str, value: &str, is_sensitive: bool) {
270        let header_name = HeaderName::try_from(name).unwrap();
271        let mut header_value = HeaderValue::try_from(value).unwrap();
272        header_value.set_sensitive(is_sensitive);
273
274        self.headers.insert(header_name.as_str().to_string(), header_value);
275    }
276
277    pub fn add_headers(&mut self, headers: BTreeMap<String, String>, are_sensitive: bool) {
278        for (name, value) in headers {
279            self.add_header(name.as_str(), value.as_str(), are_sensitive.to_owned());
280        }
281    }
282
283    pub fn bearer_auth(&mut self, token: String) {
284        self.bearer_auth = Some(token);
285    }
286
287    pub fn add_param(&mut self, key: String, value: String) {
288        self.query.insert(key, value);
289    }
290
291    pub fn add_params(&mut self, params: BTreeMap<String, String>) {
292        for (name, value) in params {
293            self.add_param(name, value);
294        }
295    }
296
297    pub fn set_query(&mut self, query: BTreeMap<String, String>) {
298        self.query = query;
299    }
300
301    pub fn set_body(&mut self, data: DReq) {
302        self.body = Some(data);
303    }
304
305    fn build(self) -> Result<Request<impl product_os_http_body::Body>, ProductOSRequestError> {
306        let mut request = Request::builder();
307
308        let mut query_string = String::new();
309        for (key, value) in self.query {
310            query_string.push_str(key.as_str());
311            query_string.push_str("=");
312            query_string.push_str(value.as_str());
313            query_string.push_str("&");
314        }
315
316        match query_string.strip_suffix("&") {
317            None => {},
318            Some(q) => { query_string = q.to_string(); }
319        };
320
321        let url = if self.url.to_string().contains("?") {
322            let mut u = self.url.to_string();
323            u.push_str("&");
324            u.push_str(query_string.as_str());
325            u
326        }
327        else {
328            let mut u = self.url.to_string();
329            u.push_str("?");
330            u.push_str(query_string.as_str());
331            u
332        };
333
334        let mut uri = match Uri::from_str(url.as_str()) {
335            Ok(u) => u,
336            Err(e) => {
337                tracing::error!("Invalid uri: {:?}", e);
338                Uri::default()
339            }
340        };
341
342        request = request.uri(uri);
343
344        let method = self.method.to_http_method();
345        request = request.method(method);
346
347        for (name, value) in self.headers {
348            request = request.header(name, value);
349        }
350
351        match self.bearer_auth.clone() {
352            Some(a) => {
353                match HeaderValue::from_str(a.as_str()) {
354                    Ok(auth) => { request = request.header(String::from("authorization"), auth); }
355                    Err(e) => { tracing::error!("Invalid bearer auth for header"); }
356                }
357            },
358            None => {}
359        }
360
361        match self.body {
362            Some(body) => {
363                match self.content_type {
364                    Some(BodyType::Json) => { request = request.header("content-type", "application/json"); },
365                    Some(BodyType::Form) => { request = request.header("content-type", "application/www-form-url-encoded"); },
366                    _ => ()
367                };
368
369                match request.body(body) {
370                    Ok(req) => Ok(req),
371                    Err(e) => Err(ProductOSRequestError::Error(e.to_string()))
372                }
373            },
374            None => Err(ProductOSRequestError::Error(String::from("No body provided")))
375        }
376    }
377}
378
379
380
381#[cfg(any(feature = "response", feature = "response_std"))]
382pub struct ProductOSResponse<DRes: product_os_http_body::Body> {
383    response_url: String,
384    response_async: Option<Response<DRes>>,
385}
386
387
388#[cfg(any(feature = "response", feature = "response_std"))]
389impl<DRes: product_os_http_body::Body> ProductOSResponse<DRes> {
390    pub fn new<D>(r: DRes, url: String) -> Self {
391        Self {
392            response_url: url,
393            response_async: Some(Response::new(r)),
394        }
395    }
396
397    pub fn parts(self) -> (Parts, DRes) {
398        self.response_async.unwrap().into_parts()
399    }
400
401    pub fn status(&self) -> StatusCode {
402        self.response_async.as_ref().unwrap().status()
403    }
404
405    pub fn status_code(&self) -> u16 {
406        self.status().as_u16()
407    }
408
409    pub fn get_headers(&self) -> BTreeMap<String, String> {
410        let mut map = BTreeMap::new();
411
412        let headers = self.response_async.as_ref().unwrap().headers();
413
414        for (name, value) in headers {
415            map.insert(name.to_string(), value.to_str().unwrap().to_string());
416        }
417
418        map
419    }
420
421    pub fn response_url(&self) -> &str {
422        &self.response_url
423    }
424
425    /*
426    pub fn cookie_strings(&self) -> Vec<String> {
427        let mut cookies = vec!();
428
429        match &self.response_async {
430            Some(res) => {
431                for cookie in res.cookies() {
432                    let name = cookie.name();
433                    let value = cookie.value();
434                    let domain = match cookie.domain() {
435                        Some(d) => {
436                            let mut dom = String::from(d);
437                            dom.push_str("; ");
438                            dom
439                        }
440                        None => String::new()
441                    };
442                    let secure = match cookie.secure() {
443                        true => "Secure; ",
444                        false => ""
445                    };
446
447                    let mut cookie_string = String::from(name);
448                    cookie_string.push_str("=");
449                    cookie_string.push_str(value);
450                    cookie_string.push_str("; ");
451                    cookie_string.push_str(domain.as_str());
452                    cookie_string.push_str(secure);
453                    cookies.push(cookie_string);
454                }
455            }
456            None => {}
457        }
458
459        cookies
460    }
461    */
462}
463
464
465
466
467
468#[cfg(any(feature = "request", feature = "request_std"))]
469#[derive(Clone)]
470pub struct ProductOSRequester {
471    headers: product_os_http::header::HeaderMap,
472    secure: bool,
473
474    timeout: Duration,
475    connect_timeout: Duration,
476
477    certificates: Vec<Vec<u8>>,
478
479    trust_all_certificates: bool,
480    trust_any_certificate_for_hostname: bool,
481
482    proxy: Option<Proxy>,
483
484    redirect_policy: RedirectPolicy
485}
486
487
488#[cfg(any(feature = "request", feature = "request_std"))]
489impl ProductOSRequester {
490    pub fn new() -> Self {
491        Self {
492            headers: product_os_http::header::HeaderMap::new(),
493            secure: true,
494            timeout: Duration::from_millis(1000),
495            connect_timeout: Duration::from_millis(1000),
496            certificates: vec!(),
497            trust_all_certificates: false,
498            trust_any_certificate_for_hostname: false,
499            proxy: None,
500            redirect_policy: RedirectPolicy::Default
501        }
502    }
503
504    pub fn add_header(&mut self, name: &str, value: &str, is_sensitive: bool) {
505        let header_name = product_os_http::header::HeaderName::try_from(name).unwrap();
506        let mut header_value = product_os_http::header::HeaderValue::try_from(value).unwrap();
507        header_value.set_sensitive(is_sensitive);
508
509        self.headers.append(header_name, header_value);
510    }
511
512    pub fn set_headers(&mut self, headers: BTreeMap<String, String>) {
513        let mut header_map = product_os_http::header::HeaderMap::new();
514
515        for (name, value) in headers {
516            let header_name = product_os_http::header::HeaderName::try_from(name).unwrap();
517            header_map.insert(header_name, product_os_http::header::HeaderValue::try_from(value).unwrap());
518        }
519
520        self.headers = header_map;
521    }
522
523    pub fn force_secure(&mut self, sec: bool) {
524        self.secure = sec;
525    }
526
527    pub fn trust_all_certificates(&mut self, trust: bool) {
528        self.trust_all_certificates = trust;
529    }
530
531    pub fn trust_any_certificate_for_hostname(&mut self, trust: bool) {
532        self.trust_any_certificate_for_hostname = trust;
533    }
534
535    pub fn set_timeout(&mut self, time: u64) {
536        self.timeout = Duration::from_millis(time);
537    }
538
539    pub fn set_connect_timeout(&mut self, time: u64) {
540        self.connect_timeout = Duration::from_millis(time);
541    }
542
543    pub fn add_trusted_certificate_pem(&mut self, certificate: Vec<u8>) {
544        self.certificates.push(certificate);
545    }
546
547    pub fn get_trusted_certificates(&self) -> &Vec<Vec<u8>> {
548        &self.certificates
549    }
550
551    pub fn set_redirect_policy(&mut self, policy: RedirectPolicy) {
552        self.redirect_policy = policy;
553    }
554
555    pub fn set_proxy(&mut self, proxy: Option<(Protocol, String)>) {
556        match proxy {
557            None => self.proxy = None,
558            Some((protocol, address)) => {
559                let proxy = Proxy {
560                    protocol,
561                    address
562                };
563
564                self.proxy = Some(proxy);
565            }
566        }
567    }
568
569    pub fn build<DReq: product_os_http_body::Body, DRes: product_os_http_body::Body>(&self, client: &mut impl ProductOSClient<DReq, DRes>) {
570        client.build(&self)
571    }
572
573    fn new_request<DReq: product_os_http_body::Body, DRes: product_os_http_body::Body>(&self, method: Method, url: &str, client: &mut impl ProductOSClient<DReq, DRes>) -> ProductOSRequest<DReq> {
574        client.new_request(method, url)
575    }
576
577    async fn request<DReq: product_os_http_body::Body, DRes: product_os_http_body::Body>(&self, r: &ProductOSRequest<DReq>, client: &mut impl ProductOSClient<DReq, DRes>) -> Result<ProductOSResponse<DRes>, ProductOSRequestError> {
578        client.request(r).await
579    }
580
581    async fn request_simple<DReq: product_os_http_body::Body, DRes: product_os_http_body::Body>(&self, method: Method, url: &str, client: &mut impl ProductOSClient<DReq, DRes>) -> Result<ProductOSResponse<DRes>, ProductOSRequestError> {
582        client.request_simple(method, url).await
583    }
584
585    async fn request_raw<DReq: product_os_http_body::Body, DRes: product_os_http_body::Body>(&self, r: Request<DReq>, client: &mut impl ProductOSClient<DReq, DRes>) -> Result<ProductOSResponse<DRes>, ProductOSRequestError> {
586        client.request_raw(r).await
587    }
588}
589
590
591#[cfg(any(feature = "request", feature = "request_std"))]
592#[async_trait]
593pub trait ProductOSClient<DReq: product_os_http_body::Body, DRes: product_os_http_body::Body> {
594    fn build(&mut self, requester: &ProductOSRequester);
595
596    fn new_request(&self, method: Method, url: &str) -> ProductOSRequest<DReq>;
597    async fn request(&self, r: &ProductOSRequest<DReq>) -> Result<ProductOSResponse<DRes>, ProductOSRequestError>;
598    async fn request_simple(&self, method: Method, url: &str) -> Result<ProductOSResponse<DRes>, ProductOSRequestError>;
599    async fn request_raw(&self, r: Request<DReq>) -> Result<ProductOSResponse<DRes>, ProductOSRequestError>;
600
601    #[cfg(feature = "json")]
602    async fn set_body_json(&self, r: &mut ProductOSRequest<DReq>, json: serde_json::Value);
603
604    #[cfg(feature = "form")]
605    async fn set_body_form(&self, r: &mut ProductOSRequest<DReq>, form: &str);
606
607    async fn text(&self, r: ProductOSResponse<DRes>) -> Result<String, ProductOSRequestError>;
608    #[cfg(feature = "json")]
609    async fn json(&self, r: ProductOSResponse<DRes>) -> Result<serde_json::Value, ProductOSRequestError>;
610    async fn bytes(&self, r: ProductOSResponse<DRes>) -> Result<bytes::Bytes, ProductOSRequestError>;
611}
612
613
614
615
616
617
618// TODO: Still to implement custom without reqwest
619
620#[cfg(any(all(feature = "request", feature = "custom")))]
621#[derive(Clone)]
622pub struct ProductOSRequestClient {
623    client: reqwest::Client
624}
625
626#[cfg(all(feature = "request", feature = "custom"))]
627impl ProductOSRequestClient {
628    pub fn new() -> Self {
629        Self {
630            client: reqwest::Client::new()
631        }
632    }
633
634    fn build_request<DReq: product_os_http_body::Body>(&self, request: &ProductOSRequest<DReq>) -> Result<reqwest::Request, ProductOSRequestError> {
635        let method = match request.method {
636            Method::GET => reqwest::Method::GET,
637            Method::POST => reqwest::Method::POST,
638            Method::PATCH => reqwest::Method::PATCH,
639            Method::PUT => reqwest::Method::PUT,
640            Method::DELETE => reqwest::Method::DELETE,
641            Method::TRACE => reqwest::Method::TRACE,
642            Method::HEAD => reqwest::Method::HEAD,
643            Method::OPTIONS => reqwest::Method::OPTIONS,
644            Method::CONNECT => reqwest::Method::CONNECT,
645            Method::ANY => reqwest::Method::GET
646        };
647
648        let mut r = self.client.request(method, request.url);
649
650        let mut query = vec![];
651        for (key, value) in request.query {
652            query.push((key, value));
653        }
654        r = r.query(query.as_slice());
655
656        let mut headers = reqwest::header::HeaderMap::new();
657        for (key, value) in request.headers {
658            match reqwest::header::HeaderName::from_str(key.as_str()) {
659                Ok(k) => {
660                    match value.to_str() {
661                        Ok(val) => {
662                            match reqwest::header::HeaderValue::from_str(val) {
663                                Ok(v) => { headers.insert(k, v); }
664                                Err(_) => {}
665                            }
666                        }
667                        Err(_) => {}
668                    }
669                }
670                Err(_) => {}
671            }
672        }
673
674        r = r.headers(headers);
675
676        /*
677        match request.body {
678            None => {}
679            Some(b) => {
680                reqwest::Body::from()
681            }
682        }
683        */
684
685        match r.build() {
686            Ok(req) => Ok(req),
687            Err(e) => {
688                tracing::error!("Failed to create request: {:?}", e);
689                Err(ProductOSRequestError::Error(e.to_string()))
690            }
691        }
692    }
693}
694
695#[cfg(all(feature = "request", feature = "custom"))]
696#[async_trait]
697impl ProductOSClient<product_os_http_body::BodyBytes, product_os_http_body::BodyBytes> for ProductOSRequestClient {
698    fn build(&mut self, requester: &ProductOSRequester) {
699        let mut header_map = reqwest::header::HeaderMap::new();
700        for (name, value) in requester.headers.iter() {
701            let name = name.to_string();
702            match value.to_str() {
703                Ok(val) => {
704                    match reqwest::header::HeaderName::from_bytes(name.as_bytes()) {
705                        Ok(name) => {
706                            match reqwest::header::HeaderValue::from_str(val) {
707                                Ok(value) => { header_map.insert(name, value); }
708                                Err(_) => {}
709                            }
710                        }
711                        Err(_) => {}
712                    }
713                }
714                Err(_) => {}
715            };
716        }
717
718        let mut builder = reqwest::ClientBuilder::new()
719            .default_headers(header_map)
720            .https_only(requester.secure.to_owned())
721
722            .timeout(requester.timeout)
723            .connect_timeout(requester.connect_timeout)
724
725            .danger_accept_invalid_certs(requester.trust_all_certificates.to_owned())
726            // .danger_accept_invalid_hostnames(self.trust_any_certificate_for_hostname) // Only available with native-tls
727
728            .cookie_store(true)
729            .gzip(true)
730            .brotli(true);
731
732        for cert in &requester.certificates {
733            let certificate = reqwest::Certificate::from_der(cert.as_slice()).unwrap();
734            builder = builder.add_root_certificate(certificate);
735        }
736
737        match &requester.proxy {
738            None => {}
739            Some(proxy) => {
740                match proxy.protocol {
741                    Protocol::SOCKS5 => {
742                        let mut address_string = String::from("socks5://");
743                        address_string.push_str(proxy.address.as_str());
744
745                        match reqwest::Proxy::http(address_string.to_owned()) {
746                            Ok(proxy) => {
747                                tracing::trace!("Async proxy set successfully: {:?}", address_string);
748                                builder = builder.proxy(proxy.to_owned());
749                            },
750                            Err(e) => {
751                                tracing::error!("Failed to setup proxy: {:?}", e);
752                            }
753                        }
754                    }
755                    Protocol::HTTP => {
756                        let mut address_string = String::from("http://");
757                        address_string.push_str(proxy.address.as_str());
758
759                        match reqwest::Proxy::http(address_string.to_owned()) {
760                            Ok(proxy) => {
761                                tracing::info!("Async proxy set successfully: {:?}", address_string);
762                                builder = builder.proxy(proxy.to_owned());
763                            },
764                            Err(e) => {
765                                tracing::error!("Failed to setup proxy: {:?}", e);
766                            }
767                        }
768                    }
769                    Protocol::HTTPS => {
770                        let mut address_string = String::from("https://");
771                        address_string.push_str(proxy.address.as_str());
772
773                        match reqwest::Proxy::https(address_string.to_owned()) {
774                            Ok(proxy) => {
775                                tracing::info!("Async proxy set successfully: {:?}", address_string);
776                                builder = builder.proxy(proxy.to_owned());
777                            },
778                            Err(e) => {
779                                tracing::error!("Failed to setup proxy: {:?}", e);
780                            }
781                        }
782                    },
783                    Protocol::ALL => {
784                        let mut address_string = String::from("http://");
785                        address_string.push_str(proxy.address.as_str());
786
787                        match reqwest::Proxy::all(address_string.to_owned()) {
788                            Ok(proxy) => {
789                                tracing::info!("Async proxy set successfully: {:?}", address_string);
790                                builder = builder.proxy(proxy.to_owned());
791                            },
792                            Err(e) => {
793                                tracing::error!("Failed to setup proxy: {:?}", e);
794                            }
795                        }
796                    }
797                }
798            }
799        }
800
801        let redirect_policy = match requester.redirect_policy.to_owned() {
802            RedirectPolicy::None => reqwest::redirect::Policy::none(),
803            RedirectPolicy::Limit(hops) => reqwest::redirect::Policy::limited(hops),
804            RedirectPolicy::Default => reqwest::redirect::Policy::default()
805        };
806
807        builder = builder.redirect(redirect_policy);
808
809        tracing::trace!("Updated async client with configuration: {:?}", builder);
810
811        self.client = builder.build().unwrap();
812    }
813
814    fn new_request(&self, method: Method, url: &str) -> ProductOSRequest<product_os_http_body::BodyBytes> {
815        ProductOSRequest::new(method, url)
816    }
817
818    async fn request(&self, r: &ProductOSRequest<product_os_http_body::BodyBytes>) -> Result<ProductOSResponse<product_os_http_body::BodyBytes>, ProductOSRequestError> {
819        match self.build_request(r) {
820            Ok(request) => {
821                match self.client.execute(request).await {
822                    Ok(response) => {
823                        let url = response.url().to_string();
824                        let body = match response.bytes().await {
825                            Ok(b) => { product_os_http_body::BodyBytes::new(Bytes::from(b.as_ref())) }
826                            Err(e) => { product_os_http_body::BodyBytes::new(Bytes::new()) }
827                        };
828                        Ok(ProductOSResponse::new::<Bytes>(body, url))
829                    },
830                    Err(e) => Err(ProductOSRequestError::Error(e.to_string()))
831                }
832            }
833            Err(e) => Err(e)
834        }
835    }
836
837    async fn request_simple(&self, method: Method, url: &str) -> Result<ProductOSResponse<product_os_http_body::BodyBytes>, ProductOSRequestError> {
838        let r = ProductOSRequest::<product_os_http_body::BodyBytes>::new(method, url);
839        match self.build_request(&r) {
840            Ok(request) => {
841                match self.client.execute(request).await {
842                    Ok(response) => {
843                        let url = response.url().to_string();
844                        let body = match response.bytes().await {
845                            Ok(b) => { product_os_http_body::BodyBytes::new(Bytes::from(b.as_ref())) }
846                            Err(e) => { product_os_http_body::BodyBytes::new(Bytes::new()) }
847                        };
848                        Ok(ProductOSResponse::new::<Bytes>(body, url))
849                    },
850                    Err(e) => Err(ProductOSRequestError::Error(e.to_string()))
851                }
852            }
853            Err(e) => Err(e)
854        }
855    }
856
857    async fn request_raw(&self, r: Request<product_os_http_body::BodyBytes>) -> Result<ProductOSResponse<product_os_http_body::BodyBytes>, ProductOSRequestError> {
858        let req = ProductOSRequest::from_request(r);
859        match self.build_request(&req) {
860            Ok(request) => {
861                match self.client.execute(request).await {
862                    Ok(response) => {
863                        let url = response.url().to_string();
864                        let body = match response.bytes().await {
865                            Ok(b) => { product_os_http_body::BodyBytes::new(Bytes::from(b.as_ref())) }
866                            Err(e) => { product_os_http_body::BodyBytes::new(Bytes::new()) }
867                        };
868                        Ok(ProductOSResponse::new::<Bytes>(body, url))
869                    },
870                    Err(e) => Err(ProductOSRequestError::Error(e.to_string()))
871                }
872            }
873            Err(e) => Err(e)
874        }
875    }
876
877    #[cfg(feature = "json")]
878    async fn set_body_json(&self, r: &mut ProductOSRequest<product_os_http_body::BodyBytes>, json: serde_json::Value) {
879        let json_string = json.to_string();
880        let body = product_os_http_body::BodyBytes::new(bytes::Bytes::from(json_string));
881        r.body = Some(body);
882    }
883
884    #[cfg(feature = "form")]
885    async fn set_body_form(&self, r: &mut ProductOSRequest<product_os_http_body::BodyBytes>, form: &str) {
886        let form_string = serde_urlencoded::to_string(form);
887        let body = product_os_http_body::BodyBytes::new(bytes::Bytes::from(form_string));
888        r.body = Some(body);
889    }
890
891    async fn text(&self, r: ProductOSResponse<product_os_http_body::BodyBytes>) -> Result<String, ProductOSRequestError> {
892        match r.response_async {
893            Some(res) => {
894                match <product_os_http_body::BodyBytes as Clone>::clone(&res.body()).collect().await {
895                    Ok(body) => {
896                        match String::from_utf8(body.to_bytes().as_ref().to_vec()) {
897                            Ok(res) => Ok(res),
898                            Err(e) => Err(ProductOSRequestError::Error(e.to_string()))
899                        }
900                    }
901                    Err(e) => Err(ProductOSRequestError::Error(e.to_string()))
902                }
903            }
904            None => Err(ProductOSRequestError::Error(String::from("No response found")))
905        }
906    }
907
908    #[cfg(feature = "json")]
909    async fn json(&self, r: ProductOSResponse<product_os_http_body::BodyBytes>) -> Result<serde_json::Value, ProductOSRequestError> {
910        match r.response_async {
911            Some(res) => {
912                match <product_os_http_body::BodyBytes as Clone>::clone(&res.body()).collect().await {
913                    Ok(body) => {
914                        match String::from_utf8(body.to_bytes().as_ref().to_vec()) {
915                            Ok(res) => {
916                                match serde_json::Value::try_from(res) {
917                                    Ok(res) => Ok(res),
918                                    Err(e) => Err(ProductOSRequestError::Error(e.to_string()))
919                                }
920                            },
921                            Err(e) => Err(ProductOSRequestError::Error(e.to_string()))
922                        }
923                    }
924                    Err(e) => Err(ProductOSRequestError::Error(e.to_string()))
925                }
926            }
927            None => Err(ProductOSRequestError::Error(String::from("No response found")))
928        }
929    }
930
931    async fn bytes(&self, r: ProductOSResponse<product_os_http_body::BodyBytes>) -> Result<bytes::Bytes, ProductOSRequestError> {
932        match r.response_async {
933            Some(res) => {
934                match <product_os_http_body::BodyBytes as Clone>::clone(&res.body()).collect().await {
935                    Ok(body) => Ok(Bytes::from(body.to_bytes().as_ref())),
936                    Err(e) => Err(ProductOSRequestError::Error(e.to_string()))
937                }
938            }
939            None => Err(ProductOSRequestError::Error(String::from("No response found")))
940        }
941    }
942}
943
944
945
946
947
948#[cfg(all(feature = "request_std", feature = "std"))]
949#[derive(Clone)]
950pub struct ProductOSRequestClient {
951    client: reqwest::Client
952}
953
954#[cfg(all(feature = "request_std", feature = "std"))]
955impl ProductOSRequestClient {
956    pub fn new() -> Self {
957        Self {
958            client: reqwest::Client::new()
959        }
960    }
961
962    fn build_request<DReq: product_os_http_body::Body>(&self, request: &ProductOSRequest<DReq>) -> Result<reqwest::Request, ProductOSRequestError> {
963        let method = match request.method {
964            Method::GET => reqwest::Method::GET,
965            Method::POST => reqwest::Method::POST,
966            Method::PATCH => reqwest::Method::PATCH,
967            Method::PUT => reqwest::Method::PUT,
968            Method::DELETE => reqwest::Method::DELETE,
969            Method::TRACE => reqwest::Method::TRACE,
970            Method::HEAD => reqwest::Method::HEAD,
971            Method::OPTIONS => reqwest::Method::OPTIONS,
972            Method::CONNECT => reqwest::Method::CONNECT,
973            Method::ANY => reqwest::Method::GET
974        };
975
976        let mut r = self.client.request(method, request.url.to_string());
977
978        let mut query = vec![];
979        for (key, value) in &request.query {
980            query.push((key.to_owned(), value.to_owned()));
981        }
982        r = r.query(query.as_slice());
983
984        let mut headers = reqwest::header::HeaderMap::new();
985        for (key, value) in &request.headers {
986            match reqwest::header::HeaderName::from_str(key.as_str()) {
987                Ok(k) => {
988                    match value.to_str() {
989                        Ok(val) => {
990                            match reqwest::header::HeaderValue::from_str(val) {
991                                Ok(v) => { headers.insert(k, v); }
992                                Err(_) => {}
993                            }
994                        }
995                        Err(_) => {}
996                    }
997                }
998                Err(_) => {}
999            }
1000        }
1001
1002        r = r.headers(headers);
1003
1004        /*
1005        match request.body {
1006            None => {}
1007            Some(b) => {
1008                reqwest::Body::from()
1009            }
1010        }
1011        */
1012
1013        match r.build() {
1014            Ok(req) => Ok(req),
1015            Err(e) => {
1016                tracing::error!("Failed to create request: {:?}", e);
1017                Err(ProductOSRequestError::Error(e.to_string()))
1018            }
1019        }
1020    }
1021}
1022
1023#[cfg(all(feature = "request_std", feature = "std"))]
1024#[async_trait]
1025impl ProductOSClient<product_os_http_body::BodyBytes, product_os_http_body::BodyBytes> for ProductOSRequestClient {
1026    fn build(&mut self, requester: &ProductOSRequester) {
1027        let mut header_map = reqwest::header::HeaderMap::new();
1028        for (name, value) in requester.headers.iter() {
1029            let name = name.to_string();
1030            match value.to_str() {
1031                Ok(val) => {
1032                    match reqwest::header::HeaderName::from_bytes(name.as_bytes()) {
1033                        Ok(name) => {
1034                            match reqwest::header::HeaderValue::from_str(val) {
1035                                Ok(value) => { header_map.insert(name, value); }
1036                                Err(_) => {}
1037                            }
1038                        }
1039                        Err(_) => {}
1040                    }
1041                }
1042                Err(_) => {}
1043            };
1044        }
1045
1046        let mut builder = reqwest::ClientBuilder::new()
1047            .default_headers(header_map)
1048            .https_only(requester.secure.to_owned())
1049
1050            .timeout(requester.timeout)
1051            .connect_timeout(requester.connect_timeout)
1052
1053            .danger_accept_invalid_certs(requester.trust_all_certificates.to_owned())
1054            // .danger_accept_invalid_hostnames(self.trust_any_certificate_for_hostname) // Only available with native-tls
1055
1056            .cookie_store(true)
1057            .gzip(true)
1058            .brotli(true);
1059
1060        for cert in &requester.certificates {
1061            let certificate = reqwest::Certificate::from_der(cert.as_slice()).unwrap();
1062            builder = builder.add_root_certificate(certificate);
1063        }
1064
1065        match &requester.proxy {
1066            None => {}
1067            Some(proxy) => {
1068                match proxy.protocol {
1069                    Protocol::SOCKS5 => {
1070                        let mut address_string = String::from("socks5://");
1071                        address_string.push_str(proxy.address.as_str());
1072
1073                        match reqwest::Proxy::http(address_string.to_owned()) {
1074                            Ok(proxy) => {
1075                                tracing::trace!("Async proxy set successfully: {:?}", address_string);
1076                                builder = builder.proxy(proxy.to_owned());
1077                            },
1078                            Err(e) => {
1079                                tracing::error!("Failed to setup proxy: {:?}", e);
1080                            }
1081                        }
1082                    }
1083                    Protocol::HTTP => {
1084                        let mut address_string = String::from("product_os_http://");
1085                        address_string.push_str(proxy.address.as_str());
1086
1087                        match reqwest::Proxy::http(address_string.to_owned()) {
1088                            Ok(proxy) => {
1089                                tracing::info!("Async proxy set successfully: {:?}", address_string);
1090                                builder = builder.proxy(proxy.to_owned());
1091                            },
1092                            Err(e) => {
1093                                tracing::error!("Failed to setup proxy: {:?}", e);
1094                            }
1095                        }
1096                    }
1097                    Protocol::HTTPS => {
1098                        let mut address_string = String::from("https://");
1099                        address_string.push_str(proxy.address.as_str());
1100
1101                        match reqwest::Proxy::https(address_string.to_owned()) {
1102                            Ok(proxy) => {
1103                                tracing::info!("Async proxy set successfully: {:?}", address_string);
1104                                builder = builder.proxy(proxy.to_owned());
1105                            },
1106                            Err(e) => {
1107                                tracing::error!("Failed to setup proxy: {:?}", e);
1108                            }
1109                        }
1110                    },
1111                    Protocol::ALL => {
1112                        let mut address_string = String::from("product_os_http://");
1113                        address_string.push_str(proxy.address.as_str());
1114
1115                        match reqwest::Proxy::all(address_string.to_owned()) {
1116                            Ok(proxy) => {
1117                                tracing::info!("Async proxy set successfully: {:?}", address_string);
1118                                builder = builder.proxy(proxy.to_owned());
1119                            },
1120                            Err(e) => {
1121                                tracing::error!("Failed to setup proxy: {:?}", e);
1122                            }
1123                        }
1124                    }
1125                }
1126            }
1127        }
1128
1129        let redirect_policy = match requester.redirect_policy.to_owned() {
1130            RedirectPolicy::None => reqwest::redirect::Policy::none(),
1131            RedirectPolicy::Limit(hops) => reqwest::redirect::Policy::limited(hops),
1132            RedirectPolicy::Default => reqwest::redirect::Policy::default()
1133        };
1134
1135        builder = builder.redirect(redirect_policy);
1136
1137        tracing::trace!("Updated async client with configuration: {:?}", builder);
1138
1139        self.client = builder.build().unwrap();
1140    }
1141
1142    fn new_request(&self, method: Method, url: &str) -> ProductOSRequest<product_os_http_body::BodyBytes> {
1143        ProductOSRequest::new(method, url)
1144    }
1145
1146    async fn request(&self, r: &ProductOSRequest<product_os_http_body::BodyBytes>) -> Result<ProductOSResponse<product_os_http_body::BodyBytes>, ProductOSRequestError> {
1147        match self.build_request(r) {
1148            Ok(request) => {
1149                match self.client.execute(request).await {
1150                    Ok(response) => {
1151                        let url = response.url().to_string();
1152                        let body = match response.bytes().await {
1153                            Ok(b) => { product_os_http_body::BodyBytes::new(Bytes::from(b)) }
1154                            Err(e) => { product_os_http_body::BodyBytes::new(Bytes::new()) }
1155                        };
1156                        Ok(ProductOSResponse::new::<Bytes>(body, url))
1157                    },
1158                    Err(e) => Err(ProductOSRequestError::Error(e.to_string()))
1159                }
1160            }
1161            Err(e) => Err(e)
1162        }
1163    }
1164
1165    async fn request_simple(&self, method: Method, url: &str) -> Result<ProductOSResponse<product_os_http_body::BodyBytes>, ProductOSRequestError> {
1166        let r = ProductOSRequest::<product_os_http_body::BodyBytes>::new(method, url);
1167        match self.build_request(&r) {
1168            Ok(request) => {
1169                match self.client.execute(request).await {
1170                    Ok(response) => {
1171                        let url = response.url().to_string();
1172                        let body = match response.bytes().await {
1173                            Ok(b) => { product_os_http_body::BodyBytes::new(Bytes::from(b)) }
1174                            Err(e) => { product_os_http_body::BodyBytes::new(Bytes::new()) }
1175                        };
1176                        Ok(ProductOSResponse::new::<Bytes>(body, url))
1177                    },
1178                    Err(e) => Err(ProductOSRequestError::Error(e.to_string()))
1179                }
1180            }
1181            Err(e) => Err(e)
1182        }
1183    }
1184
1185    async fn request_raw(&self, r: Request<product_os_http_body::BodyBytes>) -> Result<ProductOSResponse<product_os_http_body::BodyBytes>, ProductOSRequestError> {
1186        let req = ProductOSRequest::from_request(r);
1187        match self.build_request(&req) {
1188            Ok(request) => {
1189                match self.client.execute(request).await {
1190                    Ok(response) => {
1191                        let url = response.url().to_string();
1192                        let body = match response.bytes().await {
1193                            Ok(b) => { product_os_http_body::BodyBytes::new(Bytes::from(b)) }
1194                            Err(e) => { product_os_http_body::BodyBytes::new(Bytes::new()) }
1195                        };
1196                        Ok(ProductOSResponse::new::<Bytes>(body, url))
1197                    },
1198                    Err(e) => Err(ProductOSRequestError::Error(e.to_string()))
1199                }
1200            }
1201            Err(e) => Err(e)
1202        }
1203    }
1204
1205    #[cfg(feature = "json")]
1206    async fn set_body_json(&self, r: &mut ProductOSRequest::<product_os_http_body::BodyBytes>, json: serde_json::Value) {
1207        let json_string = json.to_string();
1208        let body = product_os_http_body::BodyBytes::new(bytes::Bytes::from(json_string));
1209        r.body = Some(body);
1210    }
1211
1212    #[cfg(feature = "form")]
1213    async fn set_body_form(&self, r: &mut ProductOSRequest::<product_os_http_body::BodyBytes>, form: &str) {
1214        let form_string = serde_urlencoded::to_string(form).unwrap();
1215        let body = product_os_http_body::BodyBytes::new(bytes::Bytes::from(form_string));
1216        r.body = Some(body);
1217    }
1218
1219    async fn text(&self, r: ProductOSResponse<product_os_http_body::BodyBytes>) -> Result<String, ProductOSRequestError> {
1220        match r.response_async {
1221            Some(res) => {
1222                match <product_os_http_body::BodyBytes as Clone>::clone(&res.body()).collect().await {
1223                    Ok(body) => {
1224                        match String::from_utf8(body.to_bytes().as_ref().to_vec()) {
1225                            Ok(res) => Ok(res),
1226                            Err(e) => Err(ProductOSRequestError::Error(e.to_string()))
1227                        }
1228                    }
1229                    Err(e) => Err(ProductOSRequestError::Error(e.to_string()))
1230                }
1231            }
1232            None => Err(ProductOSRequestError::Error(String::from("No response found")))
1233        }
1234    }
1235
1236    #[cfg(feature = "json")]
1237    async fn json(&self, r: ProductOSResponse<product_os_http_body::BodyBytes>) -> Result<serde_json::Value, ProductOSRequestError> {
1238        match r.response_async {
1239            Some(res) => {
1240                match <product_os_http_body::BodyBytes as Clone>::clone(&res.body()).collect().await {
1241                    Ok(body) => {
1242                        match String::from_utf8(body.to_bytes().as_ref().to_vec()) {
1243                            Ok(res) => {
1244                                match serde_json::Value::try_from(res) {
1245                                    Ok(res) => Ok(res),
1246                                    Err(e) => Err(ProductOSRequestError::Error(e.to_string()))
1247                                }
1248                            },
1249                            Err(e) => Err(ProductOSRequestError::Error(e.to_string()))
1250                        }
1251                    }
1252                    Err(e) => Err(ProductOSRequestError::Error(e.to_string()))
1253                }
1254            }
1255            None => Err(ProductOSRequestError::Error(String::from("No response found")))
1256        }
1257    }
1258
1259    async fn bytes(&self, r: ProductOSResponse<product_os_http_body::BodyBytes>) -> Result<bytes::Bytes, ProductOSRequestError> {
1260        match r.response_async {
1261            Some(res) => {
1262                match <product_os_http_body::BodyBytes as Clone>::clone(&res.body()).collect().await {
1263                    Ok(body) => Ok(Bytes::from(body.to_bytes())),
1264                    Err(e) => Err(ProductOSRequestError::Error(e.to_string()))
1265                }
1266            }
1267            None => Err(ProductOSRequestError::Error(String::from("No response found")))
1268        }
1269    }
1270}
1271
1272
1273