product_os_request/
lib.rs

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