• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 use std::sync::Arc;
15 
16 use ylong_http::request::uri::Uri;
17 
18 use super::pool::ConnPool;
19 use super::timeout::TimeoutFuture;
20 use super::{conn, Connector, HttpConnector, Request, Response};
21 use crate::async_impl::dns::{DefaultDnsResolver, Resolver};
22 use crate::async_impl::request::Message;
23 use crate::error::HttpClientError;
24 use crate::runtime::timeout;
25 #[cfg(feature = "__tls")]
26 use crate::util::c_openssl::verify::PubKeyPins;
27 #[cfg(all(target_os = "linux", feature = "ylong_base", feature = "__tls"))]
28 use crate::util::config::FchownConfig;
29 use crate::util::config::{
30     ClientConfig, ConnectorConfig, HttpConfig, HttpVersion, Proxy, Redirect, Timeout,
31 };
32 use crate::util::dispatcher::{Conn, TimeInfoConn};
33 use crate::util::interceptor::{IdleInterceptor, Interceptor, Interceptors};
34 use crate::util::normalizer::RequestFormatter;
35 use crate::util::proxy::Proxies;
36 use crate::util::redirect::{RedirectInfo, Trigger};
37 use crate::util::request::RequestArc;
38 #[cfg(feature = "__tls")]
39 use crate::CertVerifier;
40 use crate::{ErrorKind, Retry};
41 
42 /// HTTP asynchronous client implementation. Users can use `async_impl::Client`
43 /// to send `Request` asynchronously.
44 ///
45 /// `async_impl::Client` depends on a [`async_impl::Connector`] that can be
46 /// customized by the user.
47 ///
48 /// [`async_impl::Connector`]: Connector
49 ///
50 /// # Examples
51 ///
52 /// ```no_run
53 /// use ylong_http_client::async_impl::{Body, Client, Request};
54 /// use ylong_http_client::HttpClientError;
55 ///
56 /// async fn async_client() -> Result<(), HttpClientError> {
57 ///     // Creates a new `Client`.
58 ///     let client = Client::new();
59 ///
60 ///     // Creates a new `Request`.
61 ///     let request = Request::builder().body(Body::empty())?;
62 ///
63 ///     // Sends `Request` and wait for the `Response` to return asynchronously.
64 ///     let response = client.request(request).await?;
65 ///
66 ///     // Gets the content of `Response`.
67 ///     let status = response.status();
68 ///
69 ///     Ok(())
70 /// }
71 /// ```
72 pub struct Client<C: Connector> {
73     inner: ConnPool<C, C::Stream>,
74     config: ClientConfig,
75     interceptors: Arc<Interceptors>,
76 }
77 
78 impl Client<HttpConnector> {
79     /// Creates a new, default `Client`, which uses
80     /// [`async_impl::HttpConnector`].
81     ///
82     /// [`async_impl::HttpConnector`]: HttpConnector
83     ///
84     /// # Examples
85     ///
86     /// ```
87     /// use ylong_http_client::async_impl::Client;
88     ///
89     /// let client = Client::new();
90     /// ```
new() -> Self91     pub fn new() -> Self {
92         Self::with_connector(HttpConnector::default())
93     }
94 
95     /// Creates a new, default `AsyncClient` with a given dns resolver.
96     /// # Examples
97     ///
98     /// ```
99     /// use ylong_http_client::async_impl::{Client, DefaultDnsResolver};
100     ///
101     /// let client = Client::with_dns_resolver(DefaultDnsResolver::default());
102     /// ```
with_dns_resolver<R>(resolver: R) -> Self where R: Resolver,103     pub fn with_dns_resolver<R>(resolver: R) -> Self
104     where
105         R: Resolver,
106     {
107         Self::with_connector(HttpConnector::with_dns_resolver(resolver))
108     }
109 
110     /// Creates a new, default [`async_impl::ClientBuilder`].
111     ///
112     /// [`async_impl::ClientBuilder`]: ClientBuilder
113     ///
114     /// # Examples
115     ///
116     /// ```
117     /// use ylong_http_client::async_impl::Client;
118     ///
119     /// let builder = Client::builder();
120     /// ```
builder() -> ClientBuilder121     pub fn builder() -> ClientBuilder {
122         ClientBuilder::new()
123     }
124 }
125 
126 impl<C: Connector> Client<C> {
127     /// Creates a new, default `Client` with a given connector.
128     ///
129     /// # Examples
130     ///
131     /// ```
132     /// use ylong_http_client::async_impl::{Client, HttpConnector};
133     ///
134     /// let client = Client::with_connector(HttpConnector::default());
135     /// ```
with_connector(connector: C) -> Self136     pub fn with_connector(connector: C) -> Self {
137         Self {
138             inner: ConnPool::new(HttpConfig::default(), connector),
139             config: ClientConfig::default(),
140             interceptors: Arc::new(IdleInterceptor),
141         }
142     }
143 
144     /// Sends HTTP `Request` asynchronously.
145     ///
146     /// # Examples
147     ///
148     /// ```
149     /// use ylong_http_client::async_impl::{Body, Client, Request};
150     /// use ylong_http_client::HttpClientError;
151     ///
152     /// async fn async_client() -> Result<(), HttpClientError> {
153     ///     let client = Client::new();
154     ///     let response = client
155     ///         .request(Request::builder().body(Body::empty())?)
156     ///         .await?;
157     ///     Ok(())
158     /// }
159     /// ```
request(&self, request: Request) -> Result<Response, HttpClientError>160     pub async fn request(&self, request: Request) -> Result<Response, HttpClientError> {
161         let mut request = RequestArc::new(request);
162         let mut retries = self.config.retry.times().unwrap_or(0);
163         loop {
164             let response = if let Some(timeout) = self.config.total_timeout.inner() {
165                 TimeoutFuture::new(
166                     self.send_request(request.clone()),
167                     timeout,
168                     |response, timeout| {
169                         response.body_mut().set_total_sleep(timeout);
170                     },
171                 )
172                 .await
173             } else {
174                 self.send_request(request.clone()).await
175             };
176             if let Err(ref err) = response {
177                 if retries > 0 && request.ref_mut().body_mut().reuse().await.is_ok() {
178                     self.interceptors.intercept_retry(err)?;
179                     retries -= 1;
180                     continue;
181                 }
182             }
183             return response;
184         }
185     }
186 
187     /// Enables a total timeout.
188     ///
189     /// The timeout is applied from when the request starts connection util the
190     /// response body has finished, and only affects subsequent tasks.
191     ///
192     /// # Examples
193     ///
194     /// ```
195     /// use ylong_http_client::async_impl::Client;
196     /// use ylong_http_client::{HttpClientError, Timeout};
197     ///
198     /// let mut client = Client::new();
199     /// client.total_timeout(Timeout::none());
200     /// ```
total_timeout(&mut self, timeout: Timeout)201     pub fn total_timeout(&mut self, timeout: Timeout) {
202         self.config.total_timeout = timeout;
203     }
204 }
205 
206 impl<C: Connector> Client<C> {
send_request(&self, request: RequestArc) -> Result<Response, HttpClientError>207     async fn send_request(&self, request: RequestArc) -> Result<Response, HttpClientError> {
208         let mut response = self.send_unformatted_request(request.clone()).await?;
209         response = self.redirect(response, request.clone()).await?;
210         #[cfg(feature = "http3")]
211         self.inner.set_alt_svcs(request, &response);
212         Ok(response)
213     }
214 
send_unformatted_request( &self, mut request: RequestArc, ) -> Result<Response, HttpClientError>215     async fn send_unformatted_request(
216         &self,
217         mut request: RequestArc,
218     ) -> Result<Response, HttpClientError> {
219         RequestFormatter::new(request.ref_mut()).format()?;
220         let mut info_conn = self.connect_to(request.ref_mut().uri()).await?;
221         request
222             .ref_mut()
223             .time_group_mut()
224             .update_transport_conn_time(info_conn.time_group());
225         let mut conn = info_conn.connection();
226         self.interceptors.intercept_connection(conn.get_detail())?;
227         self.send_request_on_conn(conn, request).await
228     }
229 
connect_to(&self, uri: &Uri) -> Result<TimeInfoConn<C::Stream>, HttpClientError>230     async fn connect_to(&self, uri: &Uri) -> Result<TimeInfoConn<C::Stream>, HttpClientError> {
231         if let Some(dur) = self.config.connect_timeout.inner() {
232             match timeout(dur, self.inner.connect_to(uri)).await {
233                 Err(elapsed) => err_from_other!(Timeout, elapsed),
234                 Ok(Ok(conn)) => Ok(conn),
235                 Ok(Err(e)) => Err(e),
236             }
237         } else {
238             self.inner.connect_to(uri).await
239         }
240     }
241 
send_request_on_conn( &self, conn: Conn<C::Stream>, request: RequestArc, ) -> Result<Response, HttpClientError>242     async fn send_request_on_conn(
243         &self,
244         conn: Conn<C::Stream>,
245         request: RequestArc,
246     ) -> Result<Response, HttpClientError> {
247         let message = Message {
248             request,
249             interceptor: Arc::clone(&self.interceptors),
250         };
251         if let Some(timeout) = self.config.request_timeout.inner() {
252             TimeoutFuture::new(
253                 conn::request(conn, message),
254                 timeout,
255                 |response, timeout| {
256                     response.body_mut().set_request_sleep(timeout);
257                 },
258             )
259             .await
260         } else {
261             conn::request(conn, message).await
262         }
263     }
264 
redirect( &self, response: Response, mut request: RequestArc, ) -> Result<Response, HttpClientError>265     async fn redirect(
266         &self,
267         response: Response,
268         mut request: RequestArc,
269     ) -> Result<Response, HttpClientError> {
270         let mut response = response;
271         let mut info = RedirectInfo::new();
272         loop {
273             match self
274                 .config
275                 .redirect
276                 .inner()
277                 .redirect(request.ref_mut(), &response, &mut info)?
278             {
279                 Trigger::NextLink => {
280                     // Here the body should be reused.
281                     request
282                         .ref_mut()
283                         .body_mut()
284                         .reuse()
285                         .await
286                         .map_err(|e| HttpClientError::from_io_error(ErrorKind::Redirect, e))?;
287                     self.interceptors
288                         .intercept_redirect_request(request.ref_mut())?;
289                     response = self.send_unformatted_request(request.clone()).await?;
290                     self.interceptors.intercept_redirect_response(&response)?;
291                 }
292                 Trigger::Stop => {
293                     self.interceptors.intercept_response(&response)?;
294                     return Ok(response);
295                 }
296             }
297         }
298     }
299 }
300 
301 impl Default for Client<HttpConnector> {
default() -> Self302     fn default() -> Self {
303         Self::new()
304     }
305 }
306 
307 /// A builder which is used to construct `async_impl::Client`.
308 ///
309 /// # Examples
310 ///
311 /// ```
312 /// use ylong_http_client::async_impl::ClientBuilder;
313 ///
314 /// let client = ClientBuilder::new().build();
315 /// ```
316 pub struct ClientBuilder {
317     /// Options and flags that is related to `HTTP`.
318     http: HttpConfig,
319 
320     /// Options and flags that is related to `Client`.
321     client: ClientConfig,
322 
323     /// Options and flags that is related to `Proxy`.
324     proxies: Proxies,
325 
326     #[cfg(all(target_os = "linux", feature = "ylong_base", feature = "__tls"))]
327     /// Fchown configuration.
328     fchown: Option<FchownConfig>,
329 
330     /// Interceptor for all stages.
331     interceptors: Arc<Interceptors>,
332     /// Resolver to http DNS.
333     resolver: Arc<dyn Resolver>,
334 
335     /// Options and flags that is related to `TLS`.
336     #[cfg(feature = "__tls")]
337     tls: crate::util::TlsConfigBuilder,
338 }
339 
340 impl ClientBuilder {
341     /// Creates a new, default `ClientBuilder`.
342     ///
343     /// # Examples
344     ///
345     /// ```
346     /// use ylong_http_client::async_impl::ClientBuilder;
347     ///
348     /// let builder = ClientBuilder::new();
349     /// ```
new() -> Self350     pub fn new() -> Self {
351         Self {
352             http: HttpConfig::default(),
353             client: ClientConfig::default(),
354             proxies: Proxies::default(),
355             #[cfg(all(target_os = "linux", feature = "ylong_base", feature = "__tls"))]
356             fchown: None,
357             interceptors: Arc::new(IdleInterceptor),
358             resolver: Arc::new(DefaultDnsResolver::default()),
359             #[cfg(feature = "__tls")]
360             tls: crate::util::TlsConfig::builder(),
361         }
362     }
363 
364     /// Only use HTTP/1.x.
365     ///
366     /// # Examples
367     ///
368     /// ```
369     /// use ylong_http_client::async_impl::ClientBuilder;
370     ///
371     /// let builder = ClientBuilder::new().http1_only();
372     /// ```
373     #[cfg(feature = "http1_1")]
http1_only(mut self) -> Self374     pub fn http1_only(mut self) -> Self {
375         self.http.version = HttpVersion::Http1;
376         self
377     }
378 
379     /// Enables a total timeout.
380     ///
381     /// The timeout is applied from when the request starts connection util the
382     /// response body has finished.
383     ///
384     /// # Examples
385     ///
386     /// ```
387     /// use ylong_http_client::async_impl::ClientBuilder;
388     /// use ylong_http_client::Timeout;
389     ///
390     /// let builder = ClientBuilder::new().total_timeout(Timeout::none());
391     /// ```
total_timeout(mut self, timeout: Timeout) -> Self392     pub fn total_timeout(mut self, timeout: Timeout) -> Self {
393         self.client.total_timeout = timeout;
394         self
395     }
396 
397     /// Enables a request timeout.
398     ///
399     /// The timeout is applied from when the request is sent util the
400     /// response body has finished.
401     ///
402     /// # Examples
403     ///
404     /// ```
405     /// use ylong_http_client::async_impl::ClientBuilder;
406     /// use ylong_http_client::Timeout;
407     ///
408     /// let builder = ClientBuilder::new().request_timeout(Timeout::none());
409     /// ```
request_timeout(mut self, timeout: Timeout) -> Self410     pub fn request_timeout(mut self, timeout: Timeout) -> Self {
411         self.client.request_timeout = timeout;
412         self
413     }
414 
415     /// Sets a timeout for only the connect phase of `Client`.
416     ///
417     /// Default is `Timeout::none()`.
418     ///
419     /// # Examples
420     ///
421     /// ```
422     /// use ylong_http_client::async_impl::ClientBuilder;
423     /// use ylong_http_client::Timeout;
424     ///
425     /// let builder = ClientBuilder::new().connect_timeout(Timeout::none());
426     /// ```
connect_timeout(mut self, timeout: Timeout) -> Self427     pub fn connect_timeout(mut self, timeout: Timeout) -> Self {
428         self.client.connect_timeout = timeout;
429         self
430     }
431 
432     /// Sets a `Redirect` for this client.
433     ///
434     /// Default will follow redirects up to a maximum of 10.
435     ///
436     /// # Examples
437     ///
438     /// ```
439     /// use ylong_http_client::async_impl::ClientBuilder;
440     /// use ylong_http_client::Redirect;
441     ///
442     /// let builder = ClientBuilder::new().redirect(Redirect::none());
443     /// ```
redirect(mut self, redirect: Redirect) -> Self444     pub fn redirect(mut self, redirect: Redirect) -> Self {
445         self.client.redirect = redirect;
446         self
447     }
448 
449     /// Sets a `Fchown` for this client.
450     ///
451     /// Default will not set the owner of the file descriptor.
452     ///
453     /// # Examples
454     ///
455     /// ```
456     /// use ylong_http_client::async_impl::ClientBuilder;
457     ///
458     /// let builder = ClientBuilder::new().sockets_owner(1000, 1000);
459     /// ```
460     #[cfg(all(target_os = "linux", feature = "ylong_base", feature = "__tls"))]
sockets_owner(mut self, uid: u32, gid: u32) -> Self461     pub fn sockets_owner(mut self, uid: u32, gid: u32) -> Self {
462         self.fchown = Some(FchownConfig::new(uid, gid));
463         self
464     }
465 
466     /// Sets retry times for this client.
467     ///
468     /// The Retry is the number of times the client will retry the request if
469     /// the response is not obtained correctly.
470     ///
471     /// # Examples
472     ///
473     /// ```
474     /// use ylong_http_client::async_impl::ClientBuilder;
475     /// use ylong_http_client::Retry;
476     ///
477     /// let builder = ClientBuilder::new().retry(Retry::max());
478     /// ```
retry(mut self, retry: Retry) -> Self479     pub fn retry(mut self, retry: Retry) -> Self {
480         self.client.retry = retry;
481         self
482     }
483 
484     /// Adds a `Proxy` to the list of proxies the `Client` will use.
485     ///
486     /// # Examples
487     ///
488     /// ```
489     /// # use ylong_http_client::async_impl::ClientBuilder;
490     /// # use ylong_http_client::{HttpClientError, Proxy};
491     ///
492     /// # fn add_proxy() -> Result<(), HttpClientError> {
493     /// let builder = ClientBuilder::new().proxy(Proxy::http("http://www.example.com").build()?);
494     /// # Ok(())
495     /// # }
496     /// ```
proxy(mut self, proxy: Proxy) -> Self497     pub fn proxy(mut self, proxy: Proxy) -> Self {
498         self.proxies.add_proxy(proxy.inner());
499         self
500     }
501 
502     /// Sets the maximum number of http1 connections allowed.
503     ///
504     /// By default, the maximum number of http1 connections allowed is 6.
505     ///
506     /// # Examples
507     ///
508     /// ```
509     /// use ylong_http_client::async_impl::ClientBuilder;
510     ///
511     /// let builder = ClientBuilder::new().max_h1_conn_number(5);
512     /// ```
max_h1_conn_number(mut self, number: usize) -> Self513     pub fn max_h1_conn_number(mut self, number: usize) -> Self {
514         self.http.http1_config.set_max_conn_num(number);
515         self
516     }
517 
518     /// Sets the maximum number of bytes per second allowed for data transfer.
519     ///
520     /// By default, there is no limit.
521     ///
522     /// # Examples
523     ///
524     /// ```
525     /// use ylong_http_client::async_impl::ClientBuilder;
526     ///
527     /// let builder = ClientBuilder::new().max_speed_limit(5);
528     /// ```
max_speed_limit(mut self, rate: u64) -> Self529     pub fn max_speed_limit(mut self, rate: u64) -> Self {
530         self.http.speed_config.set_max_rate(rate);
531         self
532     }
533 
534     /// Sets the minimum number of bytes per second allowed for data transfer.
535     ///
536     /// By default, there is no limit.
537     ///
538     /// # Examples
539     ///
540     /// ```
541     /// use ylong_http_client::async_impl::ClientBuilder;
542     ///
543     /// let builder = ClientBuilder::new().min_speed_limit(5);
544     /// ```
min_speed_limit(mut self, rate: u64) -> Self545     pub fn min_speed_limit(mut self, rate: u64) -> Self {
546         self.http.speed_config.set_min_rate(rate);
547         self
548     }
549 
550     /// Sets the maximum time that the speed is allowed to be below
551     /// min_speed_limit, beyond which the abort is executed.
552     ///
553     /// By default, there is no limit.
554     ///
555     /// # Examples
556     ///
557     /// ```
558     /// use ylong_http_client::async_impl::ClientBuilder;
559     ///
560     /// let builder = ClientBuilder::new().min_speed_limit(5);
561     /// ```
min_speed_interval(mut self, seconds: u64) -> Self562     pub fn min_speed_interval(mut self, seconds: u64) -> Self {
563         self.http.speed_config.set_min_speed_interval(seconds);
564         self
565     }
566 
567     /// Adds a `Interceptor` to the `Client`.
568     ///
569     /// # Examples
570     ///
571     /// ```
572     /// # use ylong_http_client::async_impl::ClientBuilder;
573     /// # use ylong_http_client::{HttpClientError, Interceptor};
574     ///
575     /// # fn add_interceptor<T>(interceptor: T)
576     /// # where T: Interceptor + Sync + Send + 'static,
577     /// # {
578     /// let builder = ClientBuilder::new().interceptor(interceptor);
579     /// # }
580     /// ```
interceptor<T>(mut self, interceptors: T) -> Self where T: Interceptor + Sync + Send + 'static,581     pub fn interceptor<T>(mut self, interceptors: T) -> Self
582     where
583         T: Interceptor + Sync + Send + 'static,
584     {
585         self.interceptors = Arc::new(interceptors);
586         self
587     }
588 
589     /// Adds a dns `Resolver` to the `Client`.
590     ///
591     /// # Example
592     ///
593     /// ```
594     /// use ylong_http_client::async_impl::{ClientBuilder, DefaultDnsResolver};
595     ///
596     /// let builder = ClientBuilder::new().dns_resolver(DefaultDnsResolver::default());
597     /// ```
dns_resolver<R>(mut self, resolver: R) -> Self where R: Resolver,598     pub fn dns_resolver<R>(mut self, resolver: R) -> Self
599     where
600         R: Resolver,
601     {
602         self.resolver = Arc::new(resolver);
603         self
604     }
605 
606     /// Constructs a `Client` based on the given settings.
607     ///
608     /// # Examples
609     ///
610     /// ```
611     /// use ylong_http_client::async_impl::ClientBuilder;
612     ///
613     /// let client = ClientBuilder::new().build();
614     /// ```
build(self) -> Result<Client<HttpConnector>, HttpClientError>615     pub fn build(self) -> Result<Client<HttpConnector>, HttpClientError> {
616         #[cfg(feature = "__tls")]
617         use crate::util::{AlpnProtocol, AlpnProtocolList};
618 
619         #[cfg(feature = "__tls")]
620         let origin_builder = self.tls;
621         #[cfg(feature = "__tls")]
622         let tls_builder = match self.http.version {
623             HttpVersion::Http1 => origin_builder,
624             #[cfg(feature = "http2")]
625             HttpVersion::Http2 => origin_builder.alpn_protos(AlpnProtocol::H2.wire_format_bytes()),
626             HttpVersion::Negotiate => {
627                 let supported = AlpnProtocolList::new();
628                 #[cfg(feature = "http3")]
629                 let supported = supported.extend(AlpnProtocol::H3);
630                 #[cfg(feature = "http2")]
631                 let supported = supported.extend(AlpnProtocol::H2);
632                 let supported = supported.extend(AlpnProtocol::HTTP11);
633                 origin_builder.alpn_proto_list(supported)
634             }
635             #[cfg(feature = "http3")]
636             HttpVersion::Http3 => origin_builder.alpn_protos(AlpnProtocol::H3.wire_format_bytes()),
637         };
638 
639         let config = ConnectorConfig {
640             proxies: self.proxies,
641             #[cfg(all(target_os = "linux", feature = "ylong_base", feature = "__tls"))]
642             fchown: self.fchown,
643             #[cfg(feature = "__tls")]
644             tls: tls_builder.build()?,
645             timeout: self.client.connect_timeout.clone(),
646         };
647 
648         let connector = HttpConnector::new(config, self.resolver);
649 
650         Ok(Client {
651             inner: ConnPool::new(self.http, connector),
652             config: self.client,
653             interceptors: self.interceptors,
654         })
655     }
656 }
657 
658 #[cfg(feature = "http2")]
659 impl ClientBuilder {
660     /// Only use HTTP/2.
661     ///
662     /// # Examples
663     ///
664     /// ```
665     /// use ylong_http_client::async_impl::ClientBuilder;
666     ///
667     /// let builder = ClientBuilder::new().http2_prior_knowledge();
668     /// ```
http2_prior_knowledge(mut self) -> Self669     pub fn http2_prior_knowledge(mut self) -> Self {
670         self.http.version = HttpVersion::Http2;
671         self
672     }
673 
674     /// Sets allowed max size of local cached frame, By default, 5 frames are
675     /// allowed per stream.
676     ///
677     /// # Examples
678     ///
679     /// ```
680     /// use ylong_http_client::async_impl::ClientBuilder;
681     ///
682     /// let config = ClientBuilder::new().allowed_cache_frame_size(10);
683     /// ```
allowed_cache_frame_size(mut self, size: usize) -> Self684     pub fn allowed_cache_frame_size(mut self, size: usize) -> Self {
685         self.http.http2_config.set_allowed_cache_frame_size(size);
686         self
687     }
688 
689     /// Sets whether to use huffman coding in hpack. The default is true.
690     ///
691     /// # Examples
692     ///
693     /// ```
694     /// use ylong_http_client::async_impl::ClientBuilder;
695     ///
696     /// let config = ClientBuilder::new().use_huffman_coding(true);
697     /// ```
use_huffman_coding(mut self, use_huffman: bool) -> Self698     pub fn use_huffman_coding(mut self, use_huffman: bool) -> Self {
699         self.http.http2_config.set_use_huffman_coding(use_huffman);
700         self
701     }
702 
703     /// Sets the `SETTINGS_MAX_FRAME_SIZE`.
704     ///
705     /// # Examples
706     ///
707     /// ```
708     /// use ylong_http_client::async_impl::ClientBuilder;
709     ///
710     /// let config = ClientBuilder::new().set_http2_max_frame_size(2 << 13);
711     /// ```
set_http2_max_frame_size(mut self, size: u32) -> Self712     pub fn set_http2_max_frame_size(mut self, size: u32) -> Self {
713         self.http.http2_config.set_max_frame_size(size);
714         self
715     }
716 
717     /// Sets the `SETTINGS_MAX_HEADER_LIST_SIZE`.
718     ///
719     /// # Examples
720     ///
721     /// ```
722     /// use ylong_http_client::async_impl::ClientBuilder;
723     ///
724     /// let config = ClientBuilder::new().set_http2_max_header_list_size(16 << 20);
725     /// ```
set_http2_max_header_list_size(mut self, size: u32) -> Self726     pub fn set_http2_max_header_list_size(mut self, size: u32) -> Self {
727         self.http.http2_config.set_max_header_list_size(size);
728         self
729     }
730 
731     /// Sets the `SETTINGS_HEADER_TABLE_SIZE`.
732     ///
733     /// # Examples
734     ///
735     /// ```
736     /// use ylong_http_client::async_impl::ClientBuilder;
737     ///
738     /// let config = ClientBuilder::new().set_http2_max_header_list_size(4096);
739     /// ```
set_http2_header_table_size(mut self, size: u32) -> Self740     pub fn set_http2_header_table_size(mut self, size: u32) -> Self {
741         self.http.http2_config.set_header_table_size(size);
742         self
743     }
744 
745     /// Sets the maximum connection window allowed by the client.
746     ///
747     /// # Examples
748     ///
749     /// ```
750     /// use ylong_http_client::async_impl::ClientBuilder;
751     ///
752     /// let config = ClientBuilder::new().set_conn_recv_window_size(4096);
753     /// ```
set_conn_recv_window_size(mut self, size: u32) -> Self754     pub fn set_conn_recv_window_size(mut self, size: u32) -> Self {
755         assert!(size <= crate::util::h2::MAX_FLOW_CONTROL_WINDOW);
756         self.http.http2_config.set_conn_window_size(size);
757         self
758     }
759 
760     /// Sets the `SETTINGS_INITIAL_WINDOW_SIZE`.
761     ///
762     /// # Examples
763     ///
764     /// ```
765     /// use ylong_http_client::async_impl::ClientBuilder;
766     ///
767     /// let config = ClientBuilder::new().set_stream_recv_window_size(4096);
768     /// ```
set_stream_recv_window_size(mut self, size: u32) -> Self769     pub fn set_stream_recv_window_size(mut self, size: u32) -> Self {
770         assert!(size <= crate::util::h2::MAX_FLOW_CONTROL_WINDOW);
771         self.http.http2_config.set_stream_window_size(size);
772         self
773     }
774 }
775 
776 #[cfg(feature = "http3")]
777 impl ClientBuilder {
778     /// Only use HTTP/3.
779     ///
780     /// # Examples
781     ///
782     /// ```
783     /// use ylong_http_client::async_impl::ClientBuilder;
784     ///
785     /// let builder = ClientBuilder::new().http3_prior_knowledge();
786     /// ```
http3_prior_knowledge(mut self) -> Self787     pub fn http3_prior_knowledge(mut self) -> Self {
788         self.http.version = HttpVersion::Http3;
789         self
790     }
791 
792     /// Sets the `SETTINGS_MAX_FIELD_SECTION_SIZE` defined in RFC9114
793     ///
794     /// # Examples
795     ///
796     /// ```
797     /// use ylong_http_client::async_impl::ClientBuilder;
798     ///
799     /// let builder = ClientBuilder::new().set_http3_max_field_section_size(16 * 1024);
800     /// ```
set_http3_max_field_section_size(mut self, size: u64) -> Self801     pub fn set_http3_max_field_section_size(mut self, size: u64) -> Self {
802         self.http.http3_config.set_max_field_section_size(size);
803         self
804     }
805 
806     /// Sets the `SETTINGS_QPACK_MAX_TABLE_CAPACITY` defined in RFC9204
807     ///
808     /// # Examples
809     ///
810     /// ```
811     /// use ylong_http_client::async_impl::ClientBuilder;
812     ///
813     /// let builder = ClientBuilder::new().set_http3_qpack_max_table_capacity(16 * 1024);
814     /// ```
set_http3_qpack_max_table_capacity(mut self, size: u64) -> Self815     pub fn set_http3_qpack_max_table_capacity(mut self, size: u64) -> Self {
816         self.http.http3_config.set_qpack_max_table_capacity(size);
817         self
818     }
819 
820     /// Sets the `SETTINGS_QPACK_BLOCKED_STREAMS` defined in RFC9204
821     ///
822     /// # Examples
823     ///
824     /// ```
825     /// use ylong_http_client::async_impl::ClientBuilder;
826     ///
827     /// let builder = ClientBuilder::new().set_http3_qpack_blocked_streams(10);
828     /// ```
set_http3_qpack_blocked_streams(mut self, size: u64) -> Self829     pub fn set_http3_qpack_blocked_streams(mut self, size: u64) -> Self {
830         self.http.http3_config.set_qpack_blocked_streams(size);
831         self
832     }
833 }
834 
835 #[cfg(feature = "__tls")]
836 impl ClientBuilder {
837     /// Sets the maximum allowed TLS version for connections.
838     ///
839     /// By default, there's no maximum.
840     ///
841     /// # Examples
842     ///
843     /// ```
844     /// use ylong_http_client::async_impl::ClientBuilder;
845     /// use ylong_http_client::TlsVersion;
846     ///
847     /// let builder = ClientBuilder::new().max_tls_version(TlsVersion::TLS_1_2);
848     /// ```
max_tls_version(mut self, version: crate::util::TlsVersion) -> Self849     pub fn max_tls_version(mut self, version: crate::util::TlsVersion) -> Self {
850         self.tls = self.tls.max_proto_version(version);
851         self
852     }
853 
854     /// Sets the minimum required TLS version for connections.
855     ///
856     /// By default, the TLS backend's own default is used.
857     ///
858     /// # Examples
859     ///
860     /// ```
861     /// use ylong_http_client::async_impl::ClientBuilder;
862     /// use ylong_http_client::TlsVersion;
863     ///
864     /// let builder = ClientBuilder::new().min_tls_version(TlsVersion::TLS_1_2);
865     /// ```
min_tls_version(mut self, version: crate::util::TlsVersion) -> Self866     pub fn min_tls_version(mut self, version: crate::util::TlsVersion) -> Self {
867         self.tls = self.tls.min_proto_version(version);
868         self
869     }
870 
871     /// Adds a custom root certificate.
872     ///
873     /// This can be used to connect to a server that has a self-signed.
874     /// certificate for example.
875     ///
876     /// # Examples
877     ///
878     /// ```
879     /// use ylong_http_client::async_impl::ClientBuilder;
880     /// use ylong_http_client::Certificate;
881     ///
882     /// # fn set_cert(cert: Certificate) {
883     /// let builder = ClientBuilder::new().add_root_certificate(cert);
884     /// # }
885     /// ```
add_root_certificate(mut self, certs: crate::util::Certificate) -> Self886     pub fn add_root_certificate(mut self, certs: crate::util::Certificate) -> Self {
887         use crate::c_openssl::adapter::CertificateList;
888 
889         match certs.into_inner() {
890             CertificateList::CertList(c) => {
891                 self.tls = self.tls.add_root_certificates(c);
892             }
893             CertificateList::PathList(p) => {
894                 self.tls = self.tls.add_path_certificates(p);
895             }
896         }
897         self
898     }
899 
900     /// Adds user pinned Public Key.
901     ///
902     /// Used to avoid man-in-the-middle attacks.
903     ///
904     /// # Examples
905     ///
906     /// ```
907     /// use ylong_http_client::async_impl::ClientBuilder;
908     /// use ylong_http_client::PubKeyPins;
909     ///
910     /// let pinned_key = PubKeyPins::builder()
911     /// .add("https://example.com:443",
912     /// "sha256//YhKJKSzoTt2b5FP18fvpHo7fJYqQCjAa3HWY3tvRMwE=;sha256//t62CeU2tQiqkexU74Gxa2eg7fRbEgoChTociMee9wno=")
913     /// .build()
914     /// .unwrap();
915     /// let builder = ClientBuilder::new().add_public_key_pins(pinned_key);
916     /// ```
add_public_key_pins(mut self, pin: PubKeyPins) -> Self917     pub fn add_public_key_pins(mut self, pin: PubKeyPins) -> Self {
918         self.tls = self.tls.pinning_public_key(pin);
919         self
920     }
921 
922     /// Loads trusted root certificates from a file. The file should contain a
923     /// sequence of PEM-formatted CA certificates.
924     ///
925     /// # Examples
926     ///
927     /// ```
928     /// use ylong_http_client::async_impl::ClientBuilder;
929     ///
930     /// let builder = ClientBuilder::new().tls_ca_file("ca.crt");
931     /// ```
tls_ca_file(mut self, path: &str) -> Self932     pub fn tls_ca_file(mut self, path: &str) -> Self {
933         self.tls = self.tls.ca_file(path);
934         self
935     }
936 
937     /// Sets the list of supported ciphers for protocols before `TLSv1.3`.
938     ///
939     /// See [`ciphers`] for details on the format.
940     ///
941     /// [`ciphers`]: https://www.openssl.org/docs/man1.1.0/apps/ciphers.html
942     ///
943     /// # Examples
944     ///
945     /// ```
946     /// use ylong_http_client::async_impl::ClientBuilder;
947     ///
948     /// let builder = ClientBuilder::new()
949     ///     .tls_cipher_list("DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK");
950     /// ```
tls_cipher_list(mut self, list: &str) -> Self951     pub fn tls_cipher_list(mut self, list: &str) -> Self {
952         self.tls = self.tls.cipher_list(list);
953         self
954     }
955 
956     /// Controls the use of built-in system certificates during certificate
957     /// validation. Default to `true` -- uses built-in system certs.
958     ///
959     /// # Examples
960     ///
961     /// ```
962     /// use ylong_http_client::async_impl::ClientBuilder;
963     ///
964     /// let builder = ClientBuilder::new().tls_built_in_root_certs(false);
965     /// ```
tls_built_in_root_certs(mut self, is_use: bool) -> Self966     pub fn tls_built_in_root_certs(mut self, is_use: bool) -> Self {
967         self.tls = self.tls.build_in_root_certs(is_use);
968         self
969     }
970 
971     /// Controls the use of certificates verification.
972     ///
973     /// Defaults to `false` -- verify certificates.
974     ///
975     /// # Warning
976     ///
977     /// When sets `true`, any certificate for any site will be trusted for use.
978     ///
979     /// # Examples
980     ///
981     /// ```
982     /// use ylong_http_client::async_impl::ClientBuilder;
983     ///
984     /// let builder = ClientBuilder::new().danger_accept_invalid_certs(true);
985     /// ```
danger_accept_invalid_certs(mut self, is_invalid: bool) -> Self986     pub fn danger_accept_invalid_certs(mut self, is_invalid: bool) -> Self {
987         self.tls = self.tls.danger_accept_invalid_certs(is_invalid);
988         self
989     }
990 
991     /// Controls the use of hostname verification.
992     ///
993     /// Defaults to `false` -- verify hostname.
994     ///
995     /// # Warning
996     ///
997     /// When sets `true`, any valid certificate for any site will be trusted for
998     /// use from any other.
999     ///
1000     /// # Examples
1001     ///
1002     /// ```
1003     /// use ylong_http_client::async_impl::ClientBuilder;
1004     ///
1005     /// let builder = ClientBuilder::new().danger_accept_invalid_hostnames(true);
1006     /// ```
danger_accept_invalid_hostnames(mut self, is_invalid: bool) -> Self1007     pub fn danger_accept_invalid_hostnames(mut self, is_invalid: bool) -> Self {
1008         self.tls = self.tls.danger_accept_invalid_hostnames(is_invalid);
1009         self
1010     }
1011 
1012     /// Controls the use of TLS server name indication.
1013     ///
1014     /// Defaults to `true` -- sets sni.
1015     ///
1016     /// # Examples
1017     ///
1018     /// ```
1019     /// use ylong_http_client::async_impl::ClientBuilder;
1020     ///
1021     /// let builder = ClientBuilder::new().tls_sni(true);
1022     /// ```
tls_sni(mut self, is_set_sni: bool) -> Self1023     pub fn tls_sni(mut self, is_set_sni: bool) -> Self {
1024         self.tls = self.tls.sni(is_set_sni);
1025         self
1026     }
1027 
1028     /// Controls the use of TLS certs verifier.
1029     ///
1030     /// Defaults to `None` -- sets cert_verifier.
1031     ///
1032     /// # Example
1033     ///
1034     /// ```
1035     /// use ylong_http_client::async_impl::ClientBuilder;
1036     /// use ylong_http_client::{CertVerifier, ServerCerts};
1037     ///
1038     /// pub struct CallbackTest {
1039     ///     inner: String,
1040     /// }
1041     ///
1042     /// impl CallbackTest {
1043     ///     pub(crate) fn new() -> Self {
1044     ///         Self {
1045     ///             inner: "Test".to_string(),
1046     ///         }
1047     ///     }
1048     /// }
1049     ///
1050     /// impl CertVerifier for CallbackTest {
1051     ///     fn verify(&self, certs: &ServerCerts) -> bool {
1052     ///         true
1053     ///     }
1054     /// }
1055     ///
1056     /// let verifier = CallbackTest::new();
1057     /// let builder = ClientBuilder::new().cert_verifier(verifier);
1058     /// ```
cert_verifier<T: CertVerifier + Send + Sync + 'static>(mut self, verifier: T) -> Self1059     pub fn cert_verifier<T: CertVerifier + Send + Sync + 'static>(mut self, verifier: T) -> Self {
1060         use crate::util::config::tls::DefaultCertVerifier;
1061 
1062         self.tls = self
1063             .tls
1064             .cert_verifier(Arc::new(DefaultCertVerifier::new(verifier)));
1065         self
1066     }
1067 }
1068 
1069 impl Default for ClientBuilder {
default() -> Self1070     fn default() -> Self {
1071         Self::new()
1072     }
1073 }
1074 
1075 #[cfg(test)]
1076 mod ut_async_impl_client {
1077     #[cfg(feature = "ylong_base")]
1078     use ylong_runtime::io::AsyncWriteExt;
1079 
1080     #[cfg(feature = "ylong_base")]
1081     use crate::async_impl::{Body, Request, Response};
1082     use crate::async_impl::{Client, HttpConnector};
1083     #[cfg(feature = "ylong_base")]
1084     use crate::util::test_utils::{format_header_str, TcpHandle};
1085     #[cfg(feature = "ylong_base")]
1086     use crate::{build_client_request, start_tcp_server, Retry};
1087     #[cfg(all(feature = "__tls", feature = "ylong_base"))]
1088     use crate::{CertVerifier, ServerCerts};
1089     #[cfg(feature = "__tls")]
1090     use crate::{Certificate, TlsVersion};
1091     use crate::{Proxy, Timeout};
1092 
1093     #[cfg(all(feature = "__tls", feature = "ylong_base"))]
1094     struct Verifier;
1095 
1096     #[cfg(feature = "ylong_base")]
client_request_redirect()1097     async fn client_request_redirect() {
1098         use std::sync::Arc;
1099 
1100         use ylong_http::h1::ResponseDecoder;
1101         use ylong_http::response::Response as HttpResponse;
1102 
1103         use crate::async_impl::{ClientBuilder, HttpBody};
1104         use crate::util::interceptor::IdleInterceptor;
1105         use crate::util::normalizer::BodyLength;
1106         use crate::util::request::RequestArc;
1107         use crate::util::Redirect;
1108 
1109         let response_str = "HTTP/1.1 304 \r\nAge: \t 270646 \t \t\r\nLocation: \t http://example3.com:80/foo?a=1 \t \t\r\nDate: \t Mon, 19 Dec 2022 01:46:59 GMT \t \t\r\nEtag:\t \"3147526947+gzip\" \t \t\r\n\r\n".as_bytes();
1110         let mut decoder = ResponseDecoder::new();
1111         let result = decoder.decode(response_str).unwrap().unwrap();
1112 
1113         let box_stream = Box::new("hello world".as_bytes());
1114         let content_bytes = "";
1115         let until_close = HttpBody::new(
1116             Arc::new(IdleInterceptor),
1117             BodyLength::UntilClose,
1118             box_stream,
1119             content_bytes.as_bytes(),
1120         )
1121         .unwrap();
1122         let response = HttpResponse::from_raw_parts(result.0, until_close);
1123         let response = Response::new(response);
1124         let request = Request::builder()
1125             .url("http://example1.com:80/foo?a=1")
1126             .body(Body::slice("this is a body"))
1127             .unwrap();
1128         let request = RequestArc::new(request);
1129 
1130         let client = ClientBuilder::default()
1131             .redirect(Redirect::limited(2))
1132             .connect_timeout(Timeout::from_secs(2))
1133             .build()
1134             .unwrap();
1135         let res = client.redirect(response, request.clone()).await;
1136         assert!(res.is_ok())
1137     }
1138 
1139     #[cfg(feature = "ylong_base")]
client_request_version_1_0()1140     async fn client_request_version_1_0() {
1141         let request = Request::builder()
1142             .url("http://example1.com:80/foo?a=1")
1143             .method("CONNECT")
1144             .version("HTTP/1.0")
1145             .body(Body::empty())
1146             .unwrap();
1147 
1148         let client = Client::builder().http1_only().build().unwrap();
1149         let res = client.request(request).await;
1150         assert!(res
1151             .map_err(|e| {
1152                 assert_eq!(format!("{e}"), "Request Error: Unknown METHOD in HTTP/1.0");
1153                 e
1154             })
1155             .is_err());
1156     }
1157 
1158     #[cfg(all(feature = "__tls", feature = "ylong_base"))]
1159     impl CertVerifier for Verifier {
verify(&self, certs: &ServerCerts) -> bool1160         fn verify(&self, certs: &ServerCerts) -> bool {
1161             // get version
1162             let _v = certs.version().unwrap();
1163             // get issuer
1164             let _i = certs.issuer().unwrap();
1165             // get name
1166             let _n = certs.cert_name().unwrap();
1167             // cmp cert file
1168             let cert_pem = r#"-----BEGIN CERTIFICATE-----
1169 MIIDGzCCAgMCCQCHcfe97pgvpTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB
1170 VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
1171 cyBQdHkgTHRkMB4XDTE2MDgxNDE3MDAwM1oXDTI2MDgxMjE3MDAwM1owWjELMAkG
1172 A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0
1173 IFdpZGdpdHMgUHR5IEx0ZDETMBEGA1UEAwwKZm9vYmFyLmNvbTCCASIwDQYJKoZI
1174 hvcNAQEBBQADggEPADCCAQoCggEBAKj0JYxEsxejUIX+I5GH0Hg2G0kX/y1H0+Ub
1175 3mw2/Ja5BD/yN96/7zMSumXF8uS3SkmpyiJkbyD01TSRTqjlP7/VCBlyUIChlpLQ
1176 mrGaijZiT/VCyPXqmcwFzXS5IOTpX1olJfW8rA41U1LCIcDUyFf6LtZ/v8rSeKr6
1177 TuE6SGV4WRaBm1SrjWBeHVV866CRrtSS1ieT2asFsAyOZqWhk2fakwwBDFWDhOGI
1178 ubfO+5aq9cBJbNRlzsgB3UZs3gC0O6GzbnZ6oT0TiJMeTsXXjABLUlaq/rrqFF4Y
1179 euZkkbHTFBMz288PUc3m3ZTcpN+E7+ZOUBRZXKD20K07NugqCzUCAwEAATANBgkq
1180 hkiG9w0BAQsFAAOCAQEASvYHuIl5C0NHBELPpVHNuLbQsDQNKVj3a54+9q1JkiMM
1181 6taEJYfw7K1Xjm4RoiFSHpQBh+PWZS3hToToL2Zx8JfMR5MuAirdPAy1Sia/J/qE
1182 wQdJccqmvuLkLTSlsGbEJ/LUUgOAgrgHOZM5lUgIhCneA0/dWJ3PsN0zvn69/faY
1183 oo1iiolWiIHWWBUSdr3jM2AJaVAsTmLh00cKaDNk37JB940xConBGSl98JPrNrf9
1184 dUAiT0iIBngDBdHnn/yTj+InVEFyZSKrNtiDSObFHxPcxGteHNrCPJdP1e+GqkHp
1185 HJMRZVCQpSMzvHlofHSNgzWV1MX5h1CP4SGZdBDTfA==
1186 -----END CERTIFICATE-----"#;
1187             let _c = certs.cmp_pem_cert(cert_pem.as_bytes()).unwrap();
1188             false
1189         }
1190     }
1191 
1192     #[cfg(all(feature = "__tls", feature = "ylong_base"))]
client_request_verify()1193     async fn client_request_verify() {
1194         // Creates a `async_impl::Client`
1195         let client = Client::builder()
1196             .cert_verifier(Verifier)
1197             .connect_timeout(Timeout::from_secs(10))
1198             .build()
1199             .unwrap();
1200         // Creates a `Request`.
1201         let request = Request::builder()
1202             .url("https://www.example.com")
1203             .body(Body::empty())
1204             .unwrap();
1205         // Sends request and receives a `Response`.
1206         let response = client.request(request).await;
1207         assert!(response.is_err())
1208     }
1209 
1210     /// UT test cases for `Client::builder`.
1211     ///
1212     /// # Brief
1213     /// 1. Creates a ClientBuilder by calling `Client::Builder`.
1214     /// 2. Calls `http_config`, `client_config`, `build` on the builder
1215     ///    respectively.
1216     /// 3. Checks if the result is as expected.
1217     #[cfg(feature = "http1_1")]
1218     #[test]
ut_client_builder()1219     fn ut_client_builder() {
1220         let builder = Client::builder().http1_only().build();
1221         assert!(builder.is_ok());
1222         let builder_proxy = Client::builder()
1223             .proxy(Proxy::http("http://www.example.com").build().unwrap())
1224             .build();
1225         assert!(builder_proxy.is_ok());
1226     }
1227 
1228     /// UT test cases for `Client::with_connector`.
1229     ///
1230     /// # Brief
1231     /// 1. Creates a Client by calling `Client::with_connector`.
1232     /// 2. Checks if the result is as expected.
1233     #[test]
ut_client_with_connector()1234     fn ut_client_with_connector() {
1235         let client = Client::with_connector(HttpConnector::default());
1236         assert_eq!(client.config.connect_timeout, Timeout::none())
1237     }
1238 
1239     /// UT test cases for `Client::new`.
1240     ///
1241     /// # Brief
1242     /// 1. Creates a Client by calling `Client::new`.
1243     /// 2. Checks if the result is as expected.
1244     #[test]
ut_client_new()1245     fn ut_client_new() {
1246         let client = Client::new();
1247         assert_eq!(client.config.connect_timeout, Timeout::none())
1248     }
1249 
1250     /// UT test cases for `Client::default`.
1251     ///
1252     /// # Brief
1253     /// 1. Creates a Client by calling `Client::default`.
1254     /// 2. Checks if the result is as expected.
1255     #[test]
ut_client_default()1256     fn ut_client_default() {
1257         let client = Client::default();
1258         assert_eq!(client.config.connect_timeout, Timeout::none())
1259     }
1260 
1261     /// UT test cases for `ClientBuilder::build`.
1262     ///
1263     /// # Brief
1264     /// 1. Creates a ClientBuilder by calling `Client::Builder`.
1265     /// 2. Checks if the result is as expected.
1266     #[cfg(feature = "__tls")]
1267     #[test]
ut_client_build_tls()1268     fn ut_client_build_tls() {
1269         let client = Client::builder()
1270             .max_tls_version(TlsVersion::TLS_1_3)
1271             .min_tls_version(TlsVersion::TLS_1_0)
1272             .add_root_certificate(Certificate::from_pem(b"cert").unwrap())
1273             .tls_ca_file("ca.crt")
1274             .tls_cipher_list(
1275                 "DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK",
1276             )
1277             .tls_built_in_root_certs(false)
1278             .danger_accept_invalid_certs(false)
1279             .danger_accept_invalid_hostnames(false)
1280             .tls_sni(false)
1281             .build();
1282 
1283         assert!(client.is_err());
1284     }
1285 
1286     /// UT test cases for `ClientBuilder::build`.
1287     ///
1288     /// # Brief
1289     /// 1. Creates a ClientBuilder by calling `Client::Builder`.
1290     /// 2. Checks if the result is as expected.
1291     #[cfg(feature = "__tls")]
1292     #[test]
ut_client_build_tls_pubkey_pinning()1293     fn ut_client_build_tls_pubkey_pinning() {
1294         use crate::PubKeyPins;
1295 
1296         let client = Client::builder()
1297             .tls_built_in_root_certs(true) // not use root certs
1298             .danger_accept_invalid_certs(true) // not verify certs
1299             .max_tls_version(TlsVersion::TLS_1_2)
1300             .min_tls_version(TlsVersion::TLS_1_2)
1301             .add_public_key_pins(
1302                 PubKeyPins::builder()
1303                     .add(
1304                         "https://7.249.243.101:6789",
1305                         "sha256//VHQAbNl67nmkZJNESeTKvTxb5bQmd1maWnMKG/tjcAY=",
1306                     )
1307                     .build()
1308                     .unwrap(),
1309             )
1310             .build();
1311         assert!(client.is_ok())
1312     }
1313 
1314     /// UT test cases for `ClientBuilder::default`.
1315     ///
1316     /// # Brief
1317     /// 1. Creates a `ClientBuilder` by calling `ClientBuilder::default`.
1318     /// 2. Calls `http_config`, `client_config`, `tls_config` and `build`
1319     ///    respectively.
1320     /// 3. Checks if the result is as expected.
1321     #[test]
ut_client_builder_default()1322     fn ut_client_builder_default() {
1323         use crate::async_impl::ClientBuilder;
1324         use crate::util::{Redirect, Timeout};
1325 
1326         let builder = ClientBuilder::default()
1327             .redirect(Redirect::none())
1328             .connect_timeout(Timeout::from_secs(9))
1329             .build();
1330         assert!(builder.is_ok())
1331     }
1332 
1333     /// UT test cases for `ClientBuilder::default`.
1334     ///
1335     /// # Brief
1336     /// 1. Creates a `ClientBuilder` by calling `ClientBuilder::default`.
1337     /// 2. Set redirect for client and call `Client::redirect_request`.
1338     /// 3. Checks if the result is as expected.
1339     #[cfg(feature = "ylong_base")]
1340     #[test]
ut_client_request_redirect()1341     fn ut_client_request_redirect() {
1342         let handle = ylong_runtime::spawn(async move {
1343             client_request_redirect().await;
1344         });
1345         ylong_runtime::block_on(handle).unwrap();
1346     }
1347 
1348     /// UT test cases for `Client::request`.
1349     ///
1350     /// # Brief
1351     /// 1. Creates a `Client` by calling `Client::builder()`.
1352     /// 2. Set version HTTP/1.0 for client and call `Client::request`.
1353     /// 3. Checks if the result is as expected.
1354     #[cfg(feature = "ylong_base")]
1355     #[test]
ut_client_connect_http1_0()1356     fn ut_client_connect_http1_0() {
1357         let handle = ylong_runtime::spawn(async move {
1358             client_request_version_1_0().await;
1359         });
1360         ylong_runtime::block_on(handle).unwrap();
1361     }
1362 
1363     /// UT test cases for retry of `Client::request`.
1364     ///
1365     /// # Brief
1366     /// 1. Creates a `Client` by calling `Client::builder()`.
1367     /// 2. Set version HTTP/1.0 for client and call `Client::request`.
1368     /// 3. Checks if the result is as expected.
1369     #[cfg(feature = "ylong_base")]
1370     #[test]
ut_client_request_http1_0_retry()1371     fn ut_client_request_http1_0_retry() {
1372         let request = Request::builder()
1373             .url("http://example1.com:80/foo?a=1")
1374             .method("CONNECT")
1375             .version("HTTP/1.0")
1376             .body(Body::empty())
1377             .unwrap();
1378 
1379         let retry_times = Retry::new(1).unwrap();
1380         let client = Client::builder()
1381             .retry(retry_times)
1382             .http1_only()
1383             .build()
1384             .unwrap();
1385 
1386         let handle = ylong_runtime::spawn(async move {
1387             let res = client.request(request).await;
1388             assert!(res
1389                 .map_err(|e| {
1390                     assert_eq!(format!("{e}"), "Request Error: Unknown METHOD in HTTP/1.0");
1391                     e
1392                 })
1393                 .is_err());
1394         });
1395         ylong_runtime::block_on(handle).unwrap();
1396     }
1397 
1398     /// UT test cases for certificate verify of `Client::request`.
1399     ///
1400     /// # Brief
1401     /// 1. Creates a `Client` by calling `Client::builder()`.
1402     /// 2. implement `CertVerifier` for struct `Verifier`.
1403     /// 3. Sets `CertVerifier` for this client.
1404     /// 4. Checks if the result is as expected.
1405     #[cfg(all(feature = "__tls", feature = "ylong_base"))]
1406     #[test]
ut_client_request_verify()1407     fn ut_client_request_verify() {
1408         let handle = ylong_runtime::spawn(async move {
1409             client_request_verify().await;
1410         });
1411         ylong_runtime::block_on(handle).unwrap();
1412     }
1413 
1414     /// UT test cases for certificate verify of `Client::send_request`.
1415     ///
1416     /// # Brief
1417     /// 1. Creates a `Client` by calling `Client::builder()`.
1418     /// 2. Sends a `Request` by `Client::send_request`.
1419     /// 4. Checks if the result is as expected.
1420     #[cfg(feature = "ylong_base")]
1421     #[test]
ut_client_send_request()1422     fn ut_client_send_request() {
1423         let mut handles = vec![];
1424         start_tcp_server!(
1425            Handles: handles,
1426            Response: {
1427                Status: 201,
1428                Version: "HTTP/1.1",
1429                Header: "Content-Length", "11",
1430                Body: "METHOD GET!",
1431            },
1432         );
1433         let handle = handles.pop().expect("No more handles !");
1434 
1435         let request = build_client_request!(
1436             Request: {
1437                 Method: "GET",
1438                 Path: "/data",
1439                 Addr: handle.addr.as_str(),
1440                 Header: "Content-Length", "5",
1441                 Body: Body::slice("HELLO".as_bytes()),
1442             },
1443         );
1444         let client = Client::builder()
1445             .connect_timeout(Timeout::from_secs(2))
1446             .max_h1_conn_number(10)
1447             .http1_only()
1448             .build()
1449             .unwrap();
1450 
1451         let handle = ylong_runtime::spawn(async move {
1452             let resp = client.request(request).await;
1453             assert!(resp.is_ok());
1454             let body = resp.unwrap().text().await;
1455             assert!(body.is_ok());
1456             handle
1457                 .server_shutdown
1458                 .recv()
1459                 .expect("server send order failed !");
1460         });
1461         ylong_runtime::block_on(handle).unwrap();
1462     }
1463 
1464     /// UT test cases for retry of `Client::connect_to`.
1465     ///
1466     /// # Brief
1467     /// 1. Creates a `Client` by calling `Client::builder()`.
1468     /// 2. Sets connect timeout for this client.
1469     /// 3. Checks if the result is as expected.
1470     #[cfg(feature = "ylong_base")]
1471     #[test]
ut_client_connect_to()1472     fn ut_client_connect_to() {
1473         let client = Client::builder()
1474             .connect_timeout(Timeout::from_secs(1))
1475             .http1_only()
1476             .build()
1477             .unwrap();
1478 
1479         let request = build_client_request!(
1480             Request: {
1481                 Path: "",
1482                 Addr: "198.18.0.25:80",
1483                 Body: Body::empty(),
1484             },
1485         );
1486         let handle = ylong_runtime::spawn(async move {
1487             let res = client.request(request).await;
1488             assert!(res.is_err());
1489         });
1490         ylong_runtime::block_on(handle).unwrap();
1491     }
1492 
1493     /// UT test cases for certificate verify of `Client::redirect`.
1494     ///
1495     /// # Brief
1496     /// 1. Creates a `Client` by calling `Client::builder()`.
1497     /// 2. Sends a `Request` by `Client::redirect`.
1498     /// 3. Checks if the result is as expected.
1499     #[cfg(feature = "ylong_base")]
1500     #[test]
ut_client_redirect()1501     fn ut_client_redirect() {
1502         let mut handles = vec![];
1503         start_tcp_server!(
1504            Handles: handles,
1505            Response: {
1506                Status: 302,
1507                Version: "HTTP/1.1",
1508                Header: "Content-Length", "11",
1509                Header: "Location", "http://ylong_http.com:80",
1510                Body: "METHOD GET!",
1511            },
1512         );
1513         let handle = handles.pop().expect("No more handles !");
1514 
1515         let request = build_client_request!(
1516             Request: {
1517                 Method: "GET",
1518                 Path: "/data",
1519                 Addr: handle.addr.as_str(),
1520                 Header: "Content-Length", "5",
1521                 Body: Body::slice("HELLO".as_bytes()),
1522             },
1523         );
1524         let client = Client::builder()
1525             .request_timeout(Timeout::from_secs(2))
1526             .http1_only()
1527             .build()
1528             .unwrap();
1529 
1530         let handle = ylong_runtime::spawn(async move {
1531             let resp = client.request(request).await;
1532             assert!(resp.is_err());
1533             handle
1534                 .server_shutdown
1535                 .recv()
1536                 .expect("server send order failed !");
1537         });
1538         ylong_runtime::block_on(handle).unwrap();
1539     }
1540 
1541     /// UT test cases for proxy of `Client::request`.
1542     ///
1543     /// # Brief
1544     /// 1. Creates a `Client` by calling `Client::builder()`.
1545     /// 2. Sends a `Request` by `Client::request`.
1546     /// 3. Checks if the result is as expected.
1547     #[cfg(feature = "ylong_base")]
1548     #[test]
ut_client_http_proxy()1549     fn ut_client_http_proxy() {
1550         let mut handles = vec![];
1551         start_tcp_server!(
1552            Handles: handles,
1553            Response: {
1554                Status: 201,
1555                Version: "HTTP/1.1",
1556                Header: "Content-Length", "11",
1557                Body: "METHOD GET!",
1558            },
1559         );
1560         let handle = handles.pop().expect("No more handles !");
1561 
1562         let request = build_client_request!(
1563             Request: {
1564                 Method: "GET",
1565                 Path: "/data",
1566                 Addr: "ylong_http.com",
1567                 Header: "Content-Length", "5",
1568                 Body: Body::slice("HELLO".as_bytes()),
1569             },
1570         );
1571         let client = Client::builder()
1572             .proxy(
1573                 Proxy::http(format!("http://{}{}", handle.addr.as_str(), "/data").as_str())
1574                     .build()
1575                     .expect("Http proxy build failed"),
1576             )
1577             .build()
1578             .expect("Client build failed!");
1579 
1580         let handle = ylong_runtime::spawn(async move {
1581             let resp = client.request(request).await;
1582             assert!(resp.is_ok());
1583             handle
1584                 .server_shutdown
1585                 .recv()
1586                 .expect("server send order failed !");
1587         });
1588         ylong_runtime::block_on(handle).unwrap();
1589     }
1590 
1591     /// UT test cases for sends chunk body of `Client::request`.
1592     ///
1593     /// # Brief
1594     /// 1. Creates a `Client` by calling `Client::builder()`.
1595     /// 2. Sends a `Request` by `Client::request`.
1596     /// 3. Checks if the result is as expected.
1597     #[cfg(feature = "ylong_base")]
1598     #[test]
ut_client_send_trunk_body()1599     fn ut_client_send_trunk_body() {
1600         let mut handles = vec![];
1601         start_tcp_server!(
1602            Handles: handles,
1603            Response: {
1604                Status: 201,
1605                Version: "HTTP/1.1",
1606                Header: "Content-Length", "11",
1607                Body: "METHOD GET!",
1608            },
1609         );
1610         let handle = handles.pop().expect("No more handles !");
1611 
1612         let request = build_client_request!(
1613             Request: {
1614                 Method: "GET",
1615                 Path: "/data",
1616                 Addr: handle.addr.as_str(),
1617                 Header: "Transfer-Encoding", "chunked",
1618                 Body: Body::slice("aaaaa bbbbb ccccc ddddd".as_bytes()),
1619             },
1620         );
1621         let client = Client::builder().http1_only().build().unwrap();
1622 
1623         let handle = ylong_runtime::spawn(async move {
1624             let resp = client.request(request).await;
1625             assert!(resp.is_ok());
1626             handle
1627                 .server_shutdown
1628                 .recv()
1629                 .expect("server send order failed !");
1630         });
1631         ylong_runtime::block_on(handle).unwrap();
1632     }
1633 
1634     /// UT test cases for sends no headers request of `Client::request`.
1635     ///
1636     /// # Brief
1637     /// 1. Creates a `Client` by calling `Client::builder()`.
1638     /// 2. Sends a `Request` by `Client::request`.
1639     /// 3. Checks if the result is as expected.
1640     #[cfg(feature = "ylong_base")]
1641     #[test]
ut_client_send_unknown_size()1642     fn ut_client_send_unknown_size() {
1643         let mut handles = vec![];
1644         start_tcp_server!(
1645            Handles: handles,
1646            Response: {
1647                Status: 201,
1648                Version: "HTTP/1.1",
1649                Header: "Content-Length", "11",
1650                Body: "METHOD GET!",
1651            },
1652         );
1653         let handle = handles.pop().expect("No more handles !");
1654 
1655         let request = build_client_request!(
1656             Request: {
1657                 Method: "GET",
1658                 Path: "/data",
1659                 Addr: handle.addr.as_str(),
1660                 Body: Body::empty(),
1661             },
1662         );
1663         let client = Client::builder().http1_only().build().unwrap();
1664 
1665         let handle = ylong_runtime::spawn(async move {
1666             let resp = client.request(request).await;
1667             assert!(resp.is_ok());
1668             handle
1669                 .server_shutdown
1670                 .recv()
1671                 .expect("server send order failed !");
1672         });
1673         ylong_runtime::block_on(handle).unwrap();
1674     }
1675 
1676     /// UT test cases for receive `Connection` header response of
1677     /// `Client::request`.
1678     ///
1679     /// # Brief
1680     /// 1. Creates a `Client` by calling `Client::builder()`.
1681     /// 2. Sends a `Request` by `Client::request`.
1682     /// 3. Checks if the result is as expected.
1683     #[cfg(feature = "ylong_base")]
1684     #[test]
ut_client_recv_conn_close()1685     fn ut_client_recv_conn_close() {
1686         let mut handles = vec![];
1687         start_tcp_server!(
1688            Handles: handles,
1689            Response: {
1690                Status: 201,
1691                Version: "HTTP/1.1",
1692                Header: "Content-Length", "11",
1693                Header: "Connection", "close",
1694                Body: "METHOD GET!",
1695            },
1696         );
1697         let handle = handles.pop().expect("No more handles !");
1698 
1699         let request = build_client_request!(
1700             Request: {
1701                 Method: "GET",
1702                 Path: "/data",
1703                 Addr: handle.addr.as_str(),
1704                 Header: "Content-Length", "5",
1705                 Body: Body::slice("HELLO".as_bytes()),
1706             },
1707         );
1708         let client = Client::builder().http1_only().build().unwrap();
1709 
1710         let handle = ylong_runtime::spawn(async move {
1711             let resp = client.request(request).await;
1712             assert!(resp.is_ok());
1713             handle
1714                 .server_shutdown
1715                 .recv()
1716                 .expect("server send order failed !");
1717         });
1718         ylong_runtime::block_on(handle).unwrap();
1719     }
1720 
1721     /// UT test cases for receive HTTP/1.0 response with invalid header of
1722     /// `Client::request`.
1723     ///
1724     /// # Brief
1725     /// 1. Creates a `Client` by calling `Client::builder()`.
1726     /// 2. Sends a `Request` by `Client::request`.
1727     /// 3. Checks if the result is as expected.
1728     #[cfg(feature = "ylong_base")]
1729     #[test]
ut_client_recv_http1_0_resp()1730     fn ut_client_recv_http1_0_resp() {
1731         let mut handles = vec![];
1732         start_tcp_server!(
1733            Handles: handles,
1734            Response: {
1735                Status: 201,
1736                Version: "HTTP/1.0",
1737                Header: "Content-Length", "11",
1738                Header: "Connection", "close",
1739                Body: "METHOD GET!",
1740            },
1741         );
1742         let handle = handles.pop().expect("No more handles !");
1743 
1744         let request = build_client_request!(
1745             Request: {
1746                 Method: "GET",
1747                 Version: "HTTP/1.0",
1748                 Path: "/data",
1749                 Addr: handle.addr.as_str(),
1750                 Header: "Content-Length", "5",
1751                 Body: Body::slice("HELLO".as_bytes()),
1752             },
1753         );
1754         let client = Client::builder().http1_only().build().unwrap();
1755 
1756         let handle = ylong_runtime::spawn(async move {
1757             let resp = client.request(request).await;
1758             assert!(resp.is_ok());
1759             handle
1760                 .server_shutdown
1761                 .recv()
1762                 .expect("server send order failed !");
1763         });
1764         ylong_runtime::block_on(handle).unwrap();
1765     }
1766 
1767     /// UT test cases for receive HTTP/1.0 response with transfer-encoding
1768     /// header of `Client::request`.
1769     ///
1770     /// # Brief
1771     /// 1. Creates a `Client` by calling `Client::builder()`.
1772     /// 2. Sends a `Request` by `Client::request`.
1773     /// 3. Checks if the result is as expected.
1774     #[cfg(feature = "ylong_base")]
1775     #[test]
ut_client_recv_invalid_http1_0_resp()1776     fn ut_client_recv_invalid_http1_0_resp() {
1777         let mut handles = vec![];
1778         start_tcp_server!(
1779            Handles: handles,
1780            Response: {
1781                Status: 201,
1782                Version: "HTTP/1.0",
1783                Header: "Transfer-Encoding", "chunked",
1784                Body: "0\r\n\r\n",
1785            },
1786         );
1787         let handle = handles.pop().expect("No more handles !");
1788 
1789         let request = build_client_request!(
1790             Request: {
1791                 Method: "GET",
1792                 Version: "HTTP/1.0",
1793                 Path: "/data",
1794                 Addr: handle.addr.as_str(),
1795                 Header: "Content-Length", "5",
1796                 Body: Body::slice("HELLO".as_bytes()),
1797             },
1798         );
1799         let client = Client::builder().http1_only().build().unwrap();
1800 
1801         let handle = ylong_runtime::spawn(async move {
1802             let resp = client.request(request).await;
1803             assert!(resp.is_err());
1804             handle
1805                 .server_shutdown
1806                 .recv()
1807                 .expect("server send order failed !");
1808         });
1809         ylong_runtime::block_on(handle).unwrap();
1810     }
1811 
1812     /// UT test cases for receive response when server is shutdown of
1813     /// `Client::request`.
1814     ///
1815     /// # Brief
1816     /// 1. Creates a `Client` by calling `Client::builder()`.
1817     /// 2. Sends a `Request` by `Client::request`.
1818     /// 3. Checks if the result is as expected.
1819     #[cfg(feature = "ylong_base")]
1820     #[test]
ut_client_recv_when_server_shutdown()1821     fn ut_client_recv_when_server_shutdown() {
1822         let mut handles = vec![];
1823         start_tcp_server!(Handles: handles, Shutdown: std::net::Shutdown::Both,);
1824         let handle = handles.pop().expect("No more handles !");
1825 
1826         let request = build_client_request!(
1827             Request: {
1828                 Method: "GET",
1829                 Path: "/data",
1830                 Addr: handle.addr.as_str(),
1831                 Header: "Content-Length", "5",
1832                 Body: Body::slice("HELLO".as_bytes()),
1833             },
1834         );
1835         let client = Client::builder().http1_only().build().unwrap();
1836 
1837         let handle = ylong_runtime::spawn(async move {
1838             let resp = client.request(request).await;
1839             assert!(resp.is_err());
1840             handle
1841                 .server_shutdown
1842                 .recv()
1843                 .expect("server send order failed !");
1844         });
1845         ylong_runtime::block_on(handle).unwrap();
1846     }
1847 
1848     /// UT test cases for receive response status in error of `Client::request`.
1849     ///
1850     /// # Brief
1851     /// 1. Creates a `Client` by calling `Client::builder()`.
1852     /// 2. Sends a `Request` by `Client::request`.
1853     /// 3. Checks if the result is as expected.
1854     #[cfg(feature = "ylong_base")]
1855     #[test]
ut_client_recv_error_resp_status()1856     fn ut_client_recv_error_resp_status() {
1857         let mut handles = vec![];
1858         start_tcp_server!(
1859            Handles: handles,
1860            Response: {
1861                Status: 2023,
1862                Version: "HTTP/1.1",
1863                Header: "Content-Length", "11",
1864                Header: "Connection", "close",
1865                Body: "METHOD GET!",
1866            },
1867         );
1868         let handle = handles.pop().expect("No more handles !");
1869 
1870         let request = build_client_request!(
1871             Request: {
1872                 Method: "GET",
1873                 Path: "/data",
1874                 Addr: handle.addr.as_str(),
1875                 Header: "Content-Length", "5",
1876                 Body: Body::slice("HELLO".as_bytes()),
1877             },
1878         );
1879         let client = Client::builder().http1_only().build().unwrap();
1880 
1881         let handle = ylong_runtime::spawn(async move {
1882             let resp = client.request(request).await;
1883             assert!(resp.is_err());
1884             handle
1885                 .server_shutdown
1886                 .recv()
1887                 .expect("server send order failed !");
1888         });
1889         ylong_runtime::block_on(handle).unwrap();
1890     }
1891 }
1892