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 }
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#[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 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 .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 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 .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