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::interceptor::{IdleInterceptor, Interceptor, Interceptors};
23 use crate::async_impl::request::Message;
24 use crate::error::HttpClientError;
25 use crate::runtime::timeout;
26 #[cfg(feature = "__tls")]
27 use crate::util::c_openssl::verify::PubKeyPins;
28 #[cfg(all(target_os = "linux", feature = "ylong_base", feature = "__tls"))]
29 use crate::util::config::FchownConfig;
30 use crate::util::config::{
31     ClientConfig, ConnectorConfig, HttpConfig, HttpVersion, Proxy, Redirect, Timeout,
32 };
33 use crate::util::dispatcher::Conn;
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     /// ```
newnull91     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_resolvernull103     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     /// ```
buildernull121     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_connectornull136     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     /// ```
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 = self.send_request(request.clone()).await;
165             if let Err(ref err) = response {
166                 if retries > 0 && request.ref_mut().body_mut().reuse().await.is_ok() {
167                     self.interceptors.intercept_retry(err)?;
168                     retries -= 1;
169                     continue;
170                 }
171             }
172             return response;
173         }
174     }
175 }
176 
177 impl<C: Connector> Client<C> {
178     async fn send_request(&self, request: RequestArc) -> Result<Response, HttpClientError> {
179         let mut response = self.send_unformatted_request(request.clone()).await?;
180         response = self.redirect(response, request.clone()).await?;
181         #[cfg(feature = "http3")]
182         self.inner.set_alt_svcs(request, &response);
183         Ok(response)
184     }
185 
186     async fn send_unformatted_request(
187         &self,
188         mut request: RequestArc,
189     ) -> Result<Response, HttpClientError> {
190         RequestFormatter::new(request.ref_mut()).format()?;
191         let conn = self.connect_to(request.ref_mut().uri()).await?;
192         self.send_request_on_conn(conn, request).await
193     }
194 
195     async fn connect_to(&self, uri: &Uri) -> Result<Conn<C::Stream>, HttpClientError> {
196         if let Some(dur) = self.config.connect_timeout.inner() {
197             match timeout(dur, self.inner.connect_to(uri)).await {
198                 Err(elapsed) => err_from_other!(Timeout, elapsed),
199                 Ok(Ok(conn)) => Ok(conn),
200                 Ok(Err(e)) => Err(e),
201             }
202         } else {
203             self.inner.connect_to(uri).await
204         }
205     }
206 
207     async fn send_request_on_conn(
208         &self,
209         conn: Conn<C::Stream>,
210         request: RequestArc,
211     ) -> Result<Response, HttpClientError> {
212         let message = Message {
213             request,
214             interceptor: Arc::clone(&self.interceptors),
215         };
216         if let Some(timeout) = self.config.request_timeout.inner() {
217             TimeoutFuture::new(conn::request(conn, message), timeout).await
218         } else {
219             conn::request(conn, message).await
220         }
221     }
222 
223     async fn redirect(
224         &self,
225         response: Response,
226         mut request: RequestArc,
227     ) -> Result<Response, HttpClientError> {
228         let mut response = response;
229         let mut info = RedirectInfo::new();
230         loop {
231             match self
232                 .config
233                 .redirect
234                 .inner()
235                 .redirect(request.ref_mut(), &response, &mut info)?
236             {
237                 Trigger::NextLink => {
238                     // Here the body should be reused.
239                     request
240                         .ref_mut()
241                         .body_mut()
242                         .reuse()
243                         .await
244                         .map_err(|e| HttpClientError::from_io_error(ErrorKind::Redirect, e))?;
245                     self.interceptors
246                         .intercept_redirect_request(request.ref_mut())?;
247                     response = self.send_unformatted_request(request.clone()).await?;
248                     self.interceptors.intercept_redirect_response(&response)?;
249                 }
250                 Trigger::Stop => {
251                     self.interceptors.intercept_response(&response)?;
252                     return Ok(response);
253                 }
254             }
255         }
256     }
257 }
258 
259 impl Default for Client<HttpConnector> {
defaultnull260     fn default() -> Self {
261         Self::new()
262     }
263 }
264 
265 /// A builder which is used to construct `async_impl::Client`.
266 ///
267 /// # Examples
268 ///
269 /// ```
270 /// use ylong_http_client::async_impl::ClientBuilder;
271 ///
272 /// let client = ClientBuilder::new().build();
273 /// ```
274 pub struct ClientBuilder {
275     /// Options and flags that is related to `HTTP`.
276     http: HttpConfig,
277 
278     /// Options and flags that is related to `Client`.
279     client: ClientConfig,
280 
281     /// Options and flags that is related to `Proxy`.
282     proxies: Proxies,
283 
284     #[cfg(all(target_os = "linux", feature = "ylong_base", feature = "__tls"))]
285     /// Fchown configuration.
286     fchown: Option<FchownConfig>,
287 
288     interceptors: Arc<Interceptors>,
289     /// Resolver to http DNS.
290     resolver: Arc<dyn Resolver>,
291 
292     /// Options and flags that is related to `TLS`.
293     #[cfg(feature = "__tls")]
294     tls: crate::util::TlsConfigBuilder,
295 }
296 
297 impl ClientBuilder {
298     /// Creates a new, default `ClientBuilder`.
299     ///
300     /// # Examples
301     ///
302     /// ```
303     /// use ylong_http_client::async_impl::ClientBuilder;
304     ///
305     /// let builder = ClientBuilder::new();
306     /// ```
newnull307     pub fn new() -> Self {
308         Self {
309             http: HttpConfig::default(),
310             client: ClientConfig::default(),
311             proxies: Proxies::default(),
312             #[cfg(all(target_os = "linux", feature = "ylong_base", feature = "__tls"))]
313             fchown: None,
314             interceptors: Arc::new(IdleInterceptor),
315             resolver: Arc::new(DefaultDnsResolver::default()),
316             #[cfg(feature = "__tls")]
317             tls: crate::util::TlsConfig::builder(),
318         }
319     }
320 
321     /// Only use HTTP/1.x.
322     ///
323     /// # Examples
324     ///
325     /// ```
326     /// use ylong_http_client::async_impl::ClientBuilder;
327     ///
328     /// let builder = ClientBuilder::new().http1_only();
329     /// ```
330     #[cfg(feature = "http1_1")]
http1_onlynull331     pub fn http1_only(mut self) -> Self {
332         self.http.version = HttpVersion::Http1;
333         self
334     }
335 
336     /// Enables a request timeout.
337     ///
338     /// The timeout is applied from when the request starts connection util the
339     /// response body has finished.
340     ///
341     /// # Examples
342     ///
343     /// ```
344     /// use ylong_http_client::async_impl::ClientBuilder;
345     /// use ylong_http_client::Timeout;
346     ///
347     /// let builder = ClientBuilder::new().request_timeout(Timeout::none());
348     /// ```
request_timeoutnull349     pub fn request_timeout(mut self, timeout: Timeout) -> Self {
350         self.client.request_timeout = timeout;
351         self
352     }
353 
354     /// Sets a timeout for only the connect phase of `Client`.
355     ///
356     /// Default is `Timeout::none()`.
357     ///
358     /// # Examples
359     ///
360     /// ```
361     /// use ylong_http_client::async_impl::ClientBuilder;
362     /// use ylong_http_client::Timeout;
363     ///
364     /// let builder = ClientBuilder::new().connect_timeout(Timeout::none());
365     /// ```
connect_timeoutnull366     pub fn connect_timeout(mut self, timeout: Timeout) -> Self {
367         self.client.connect_timeout = timeout;
368         self
369     }
370 
371     /// Sets a `Redirect` for this client.
372     ///
373     /// Default will follow redirects up to a maximum of 10.
374     ///
375     /// # Examples
376     ///
377     /// ```
378     /// use ylong_http_client::async_impl::ClientBuilder;
379     /// use ylong_http_client::Redirect;
380     ///
381     /// let builder = ClientBuilder::new().redirect(Redirect::none());
382     /// ```
redirectnull383     pub fn redirect(mut self, redirect: Redirect) -> Self {
384         self.client.redirect = redirect;
385         self
386     }
387 
388     /// Sets a `Fchown` for this client.
389     ///
390     /// Default will not set the owner of the file descriptor.
391     ///
392     /// # Examples
393     ///
394     /// ```
395     /// use ylong_http_client::async_impl::ClientBuilder;
396     ///
397     /// let builder = ClientBuilder::new().sockets_owner(1000, 1000);
398     /// ```
399     #[cfg(all(target_os = "linux", feature = "ylong_base", feature = "__tls"))]
sockets_ownernull400     pub fn sockets_owner(mut self, uid: u32, gid: u32) -> Self {
401         self.fchown = Some(FchownConfig::new(uid, gid));
402         self
403     }
404 
405     /// Sets retry times for this client.
406     ///
407     /// The Retry is the number of times the client will retry the request if
408     /// the response is not obtained correctly.
409     ///
410     /// # Examples
411     ///
412     /// ```
413     /// use ylong_http_client::async_impl::ClientBuilder;
414     /// use ylong_http_client::Retry;
415     ///
416     /// let builder = ClientBuilder::new().retry(Retry::max());
417     /// ```
retrynull418     pub fn retry(mut self, retry: Retry) -> Self {
419         self.client.retry = retry;
420         self
421     }
422 
423     /// Adds a `Proxy` to the list of proxies the `Client` will use.
424     ///
425     /// # Examples
426     ///
427     /// ```
428     /// # use ylong_http_client::async_impl::ClientBuilder;
429     /// # use ylong_http_client::{HttpClientError, Proxy};
430     ///
431     /// # fn add_proxy() -> Result<(), HttpClientError> {
432     /// let builder = ClientBuilder::new().proxy(Proxy::http("http://www.example.com").build()?);
433     /// # Ok(())
434     /// # }
435     /// ```
proxynull436     pub fn proxy(mut self, proxy: Proxy) -> Self {
437         self.proxies.add_proxy(proxy.inner());
438         self
439     }
440 
441     /// Adds a `Interceptor` to the `Client`.
442     ///
443     /// # Examples
444     ///
445     /// ```
446     /// # use ylong_http_client::async_impl::{ClientBuilder, Interceptor};
447     /// # use ylong_http_client::HttpClientError;
448     ///
449     /// # fn add_interceptor<T>(interceptor: T)
450     /// # where T: Interceptor + Sync + Send + 'static,
451     /// # {
452     /// let builder = ClientBuilder::new().interceptor(interceptor);
453     /// # }
454     /// ```
interceptornull455     pub fn interceptor<T>(mut self, interceptors: T) -> Self
456     where
457         T: Interceptor + Sync + Send + 'static,
458     {
459         self.interceptors = Arc::new(interceptors);
460         self
461     }
462 
463     /// Adds a dns `Resolver` to the `Client`.
464     ///
465     /// # Example
466     ///
467     /// ```
468     /// use ylong_http_client::async_impl::{ClientBuilder, DefaultDnsResolver};
469     ///
470     /// let builder = ClientBuilder::new().dns_resolver(DefaultDnsResolver::default());
471     /// ```
dns_resolvernull472     pub fn dns_resolver<R>(mut self, resolver: R) -> Self
473     where
474         R: Resolver,
475     {
476         self.resolver = Arc::new(resolver);
477         self
478     }
479 
480     /// Constructs a `Client` based on the given settings.
481     ///
482     /// # Examples
483     ///
484     /// ```
485     /// use ylong_http_client::async_impl::ClientBuilder;
486     ///
487     /// let client = ClientBuilder::new().build();
488     /// ```
buildnull489     pub fn build(self) -> Result<Client<HttpConnector>, HttpClientError> {
490         #[cfg(feature = "__tls")]
491         use crate::util::{AlpnProtocol, AlpnProtocolList};
492 
493         #[cfg(feature = "__tls")]
494         let origin_builder = self.tls;
495         #[cfg(feature = "__tls")]
496         let tls_builder = match self.http.version {
497             HttpVersion::Http1 => origin_builder,
498             #[cfg(feature = "http2")]
499             HttpVersion::Http2 => origin_builder.alpn_protos(AlpnProtocol::H2.wire_format_bytes()),
500             HttpVersion::Negotiate => {
501                 let supported = AlpnProtocolList::new();
502                 #[cfg(feature = "http3")]
503                 let supported = supported.extend(AlpnProtocol::H3);
504                 #[cfg(feature = "http2")]
505                 let supported = supported.extend(AlpnProtocol::H2);
506                 let supported = supported.extend(AlpnProtocol::HTTP11);
507                 origin_builder.alpn_proto_list(supported)
508             }
509             #[cfg(feature = "http3")]
510             HttpVersion::Http3 => origin_builder.alpn_protos(AlpnProtocol::H3.wire_format_bytes()),
511         };
512 
513         let config = ConnectorConfig {
514             proxies: self.proxies,
515             #[cfg(all(target_os = "linux", feature = "ylong_base", feature = "__tls"))]
516             fchown: self.fchown,
517             #[cfg(feature = "__tls")]
518             tls: tls_builder.build()?,
519             timeout: self.client.connect_timeout.clone(),
520         };
521 
522         let connector = HttpConnector::new(config, self.resolver);
523 
524         Ok(Client {
525             inner: ConnPool::new(self.http, connector),
526             config: self.client,
527             interceptors: self.interceptors,
528         })
529     }
530 }
531 
532 #[cfg(feature = "http2")]
533 impl ClientBuilder {
534     /// Only use HTTP/2.
535     ///
536     /// # Examples
537     ///
538     /// ```
539     /// use ylong_http_client::async_impl::ClientBuilder;
540     ///
541     /// let builder = ClientBuilder::new().http2_prior_knowledge();
542     /// ```
http2_prior_knowledgenull543     pub fn http2_prior_knowledge(mut self) -> Self {
544         self.http.version = HttpVersion::Http2;
545         self
546     }
547 
548     /// Sets allowed max size of local cached frame, By default, 5 frames are
549     /// allowed per stream.
550     ///
551     /// # Examples
552     ///
553     /// ```
554     /// use ylong_http_client::async_impl::ClientBuilder;
555     ///
556     /// let config = ClientBuilder::new().allowed_cache_frame_size(10);
557     /// ```
allowed_cache_frame_sizenull558     pub fn allowed_cache_frame_size(mut self, size: usize) -> Self {
559         self.http.http2_config.set_allowed_cache_frame_size(size);
560         self
561     }
562 
563     /// Sets whether to use huffman coding in hpack. The default is true.
564     ///
565     /// # Examples
566     ///
567     /// ```
568     /// use ylong_http_client::async_impl::ClientBuilder;
569     ///
570     /// let config = ClientBuilder::new().use_huffman_coding(true);
571     /// ```
use_huffman_codingnull572     pub fn use_huffman_coding(mut self, use_huffman: bool) -> Self {
573         self.http.http2_config.set_use_huffman_coding(use_huffman);
574         self
575     }
576 
577     /// Sets the `SETTINGS_MAX_FRAME_SIZE`.
578     ///
579     /// # Examples
580     ///
581     /// ```
582     /// use ylong_http_client::async_impl::ClientBuilder;
583     ///
584     /// let config = ClientBuilder::new().set_http2_max_frame_size(2 << 13);
585     /// ```
set_http2_max_frame_sizenull586     pub fn set_http2_max_frame_size(mut self, size: u32) -> Self {
587         self.http.http2_config.set_max_frame_size(size);
588         self
589     }
590 
591     /// Sets the `SETTINGS_MAX_HEADER_LIST_SIZE`.
592     ///
593     /// # Examples
594     ///
595     /// ```
596     /// use ylong_http_client::async_impl::ClientBuilder;
597     ///
598     /// let config = ClientBuilder::new().set_http2_max_header_list_size(16 << 20);
599     /// ```
set_http2_max_header_list_sizenull600     pub fn set_http2_max_header_list_size(mut self, size: u32) -> Self {
601         self.http.http2_config.set_max_header_list_size(size);
602         self
603     }
604 
605     /// Sets the `SETTINGS_HEADER_TABLE_SIZE`.
606     ///
607     /// # Examples
608     ///
609     /// ```
610     /// use ylong_http_client::async_impl::ClientBuilder;
611     ///
612     /// let config = ClientBuilder::new().set_http2_max_header_list_size(4096);
613     /// ```
set_http2_header_table_sizenull614     pub fn set_http2_header_table_size(mut self, size: u32) -> Self {
615         self.http.http2_config.set_header_table_size(size);
616         self
617     }
618 
619     /// Sets the maximum connection window allowed by the client.
620     ///
621     /// # Examples
622     ///
623     /// ```
624     /// use ylong_http_client::async_impl::ClientBuilder;
625     ///
626     /// let config = ClientBuilder::new().set_conn_recv_window_size(4096);
627     /// ```
set_conn_recv_window_sizenull628     pub fn set_conn_recv_window_size(mut self, size: u32) -> Self {
629         assert!(size <= crate::util::h2::MAX_FLOW_CONTROL_WINDOW);
630         self.http.http2_config.set_conn_window_size(size);
631         self
632     }
633 
634     /// Sets the `SETTINGS_INITIAL_WINDOW_SIZE`.
635     ///
636     /// # Examples
637     ///
638     /// ```
639     /// use ylong_http_client::async_impl::ClientBuilder;
640     ///
641     /// let config = ClientBuilder::new().set_stream_recv_window_size(4096);
642     /// ```
set_stream_recv_window_sizenull643     pub fn set_stream_recv_window_size(mut self, size: u32) -> Self {
644         assert!(size <= crate::util::h2::MAX_FLOW_CONTROL_WINDOW);
645         self.http.http2_config.set_stream_window_size(size);
646         self
647     }
648 }
649 
650 #[cfg(feature = "http3")]
651 impl ClientBuilder {
652     /// Only use HTTP/3.
653     ///
654     /// # Examples
655     ///
656     /// ```
657     /// use ylong_http_client::async_impl::ClientBuilder;
658     ///
659     /// let builder = ClientBuilder::new().http3_prior_knowledge();
660     /// ```
http3_prior_knowledgenull661     pub fn http3_prior_knowledge(mut self) -> Self {
662         self.http.version = HttpVersion::Http3;
663         self
664     }
665 
666     /// Sets the `SETTINGS_MAX_FIELD_SECTION_SIZE` defined in RFC9114
667     ///
668     /// # Examples
669     ///
670     /// ```
671     /// use ylong_http_client::async_impl::ClientBuilder;
672     ///
673     /// let builder = ClientBuilder::new().set_http3_max_field_section_size(16 * 1024);
674     /// ```
set_http3_max_field_section_sizenull675     pub fn set_http3_max_field_section_size(mut self, size: u64) -> Self {
676         self.http.http3_config.set_max_field_section_size(size);
677         self
678     }
679 
680     /// Sets the `SETTINGS_QPACK_MAX_TABLE_CAPACITY` defined in RFC9204
681     ///
682     /// # Examples
683     ///
684     /// ```
685     /// use ylong_http_client::async_impl::ClientBuilder;
686     ///
687     /// let builder = ClientBuilder::new().set_http3_qpack_max_table_capacity(16 * 1024);
688     /// ```
set_http3_qpack_max_table_capacitynull689     pub fn set_http3_qpack_max_table_capacity(mut self, size: u64) -> Self {
690         self.http.http3_config.set_qpack_max_table_capacity(size);
691         self
692     }
693 
694     /// Sets the `SETTINGS_QPACK_BLOCKED_STREAMS` defined in RFC9204
695     ///
696     /// # Examples
697     ///
698     /// ```
699     /// use ylong_http_client::async_impl::ClientBuilder;
700     ///
701     /// let builder = ClientBuilder::new().set_http3_qpack_blocked_streams(10);
702     /// ```
set_http3_qpack_blocked_streamsnull703     pub fn set_http3_qpack_blocked_streams(mut self, size: u64) -> Self {
704         self.http.http3_config.set_qpack_blocked_streams(size);
705         self
706     }
707 }
708 
709 #[cfg(feature = "__tls")]
710 impl ClientBuilder {
711     /// Sets the maximum allowed TLS version for connections.
712     ///
713     /// By default, there's no maximum.
714     ///
715     /// # Examples
716     ///
717     /// ```
718     /// use ylong_http_client::async_impl::ClientBuilder;
719     /// use ylong_http_client::TlsVersion;
720     ///
721     /// let builder = ClientBuilder::new().max_tls_version(TlsVersion::TLS_1_2);
722     /// ```
max_tls_versionnull723     pub fn max_tls_version(mut self, version: crate::util::TlsVersion) -> Self {
724         self.tls = self.tls.max_proto_version(version);
725         self
726     }
727 
728     /// Sets the minimum required TLS version for connections.
729     ///
730     /// By default, the TLS backend's own default is used.
731     ///
732     /// # Examples
733     ///
734     /// ```
735     /// use ylong_http_client::async_impl::ClientBuilder;
736     /// use ylong_http_client::TlsVersion;
737     ///
738     /// let builder = ClientBuilder::new().min_tls_version(TlsVersion::TLS_1_2);
739     /// ```
min_tls_versionnull740     pub fn min_tls_version(mut self, version: crate::util::TlsVersion) -> Self {
741         self.tls = self.tls.min_proto_version(version);
742         self
743     }
744 
745     /// Adds a custom root certificate.
746     ///
747     /// This can be used to connect to a server that has a self-signed.
748     /// certificate for example.
749     ///
750     /// # Examples
751     ///
752     /// ```
753     /// use ylong_http_client::async_impl::ClientBuilder;
754     /// use ylong_http_client::Certificate;
755     ///
756     /// # fn set_cert(cert: Certificate) {
757     /// let builder = ClientBuilder::new().add_root_certificate(cert);
758     /// # }
759     /// ```
add_root_certificatenull760     pub fn add_root_certificate(mut self, certs: crate::util::Certificate) -> Self {
761         use crate::c_openssl::adapter::CertificateList;
762 
763         match certs.into_inner() {
764             CertificateList::CertList(c) => {
765                 self.tls = self.tls.add_root_certificates(c);
766             }
767             CertificateList::PathList(p) => {
768                 self.tls = self.tls.add_path_certificates(p);
769             }
770         }
771         self
772     }
773 
774     /// Adds user pinned Public Key.
775     ///
776     /// Used to avoid man-in-the-middle attacks.
777     ///
778     /// # Examples
779     ///
780     /// ```
781     /// use ylong_http_client::async_impl::ClientBuilder;
782     /// use ylong_http_client::PubKeyPins;
783     ///
784     /// let pinned_key = PubKeyPins::builder()
785     /// .add("https://example.com:443",
786     /// "sha256//YhKJKSzoTt2b5FP18fvpHo7fJYqQCjAa3HWY3tvRMwE=;sha256//t62CeU2tQiqkexU74Gxa2eg7fRbEgoChTociMee9wno=")
787     /// .build()
788     /// .unwrap();
789     /// let builder = ClientBuilder::new().add_public_key_pins(pinned_key);
790     /// ```
add_public_key_pinsnull791     pub fn add_public_key_pins(mut self, pin: PubKeyPins) -> Self {
792         self.tls = self.tls.pinning_public_key(pin);
793         self
794     }
795 
796     /// Loads trusted root certificates from a file. The file should contain a
797     /// sequence of PEM-formatted CA certificates.
798     ///
799     /// # Examples
800     ///
801     /// ```
802     /// use ylong_http_client::async_impl::ClientBuilder;
803     ///
804     /// let builder = ClientBuilder::new().tls_ca_file("ca.crt");
805     /// ```
tls_ca_filenull806     pub fn tls_ca_file(mut self, path: &str) -> Self {
807         self.tls = self.tls.ca_file(path);
808         self
809     }
810 
811     /// Sets the list of supported ciphers for protocols before `TLSv1.3`.
812     ///
813     /// See [`ciphers`] for details on the format.
814     ///
815     /// [`ciphers`]: https://www.openssl.org/docs/man1.1.0/apps/ciphers.html
816     ///
817     /// # Examples
818     ///
819     /// ```
820     /// use ylong_http_client::async_impl::ClientBuilder;
821     ///
822     /// let builder = ClientBuilder::new()
823     ///     .tls_cipher_list("DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK");
824     /// ```
tls_cipher_listnull825     pub fn tls_cipher_list(mut self, list: &str) -> Self {
826         self.tls = self.tls.cipher_list(list);
827         self
828     }
829 
830     /// Controls the use of built-in system certificates during certificate
831     /// validation. Default to `true` -- uses built-in system certs.
832     ///
833     /// # Examples
834     ///
835     /// ```
836     /// use ylong_http_client::async_impl::ClientBuilder;
837     ///
838     /// let builder = ClientBuilder::new().tls_built_in_root_certs(false);
839     /// ```
tls_built_in_root_certsnull840     pub fn tls_built_in_root_certs(mut self, is_use: bool) -> Self {
841         self.tls = self.tls.build_in_root_certs(is_use);
842         self
843     }
844 
845     /// Controls the use of certificates verification.
846     ///
847     /// Defaults to `false` -- verify certificates.
848     ///
849     /// # Warning
850     ///
851     /// When sets `true`, any certificate for any site will be trusted for use.
852     ///
853     /// # Examples
854     ///
855     /// ```
856     /// use ylong_http_client::async_impl::ClientBuilder;
857     ///
858     /// let builder = ClientBuilder::new().danger_accept_invalid_certs(true);
859     /// ```
danger_accept_invalid_certsnull860     pub fn danger_accept_invalid_certs(mut self, is_invalid: bool) -> Self {
861         self.tls = self.tls.danger_accept_invalid_certs(is_invalid);
862         self
863     }
864 
865     /// Controls the use of hostname verification.
866     ///
867     /// Defaults to `false` -- verify hostname.
868     ///
869     /// # Warning
870     ///
871     /// When sets `true`, any valid certificate for any site will be trusted for
872     /// use from any other.
873     ///
874     /// # Examples
875     ///
876     /// ```
877     /// use ylong_http_client::async_impl::ClientBuilder;
878     ///
879     /// let builder = ClientBuilder::new().danger_accept_invalid_hostnames(true);
880     /// ```
danger_accept_invalid_hostnamesnull881     pub fn danger_accept_invalid_hostnames(mut self, is_invalid: bool) -> Self {
882         self.tls = self.tls.danger_accept_invalid_hostnames(is_invalid);
883         self
884     }
885 
886     /// Controls the use of TLS server name indication.
887     ///
888     /// Defaults to `true` -- sets sni.
889     ///
890     /// # Examples
891     ///
892     /// ```
893     /// use ylong_http_client::async_impl::ClientBuilder;
894     ///
895     /// let builder = ClientBuilder::new().tls_sni(true);
896     /// ```
tls_sninull897     pub fn tls_sni(mut self, is_set_sni: bool) -> Self {
898         self.tls = self.tls.sni(is_set_sni);
899         self
900     }
901 
902     /// Controls the use of TLS certs verifier.
903     ///
904     /// Defaults to `None` -- sets cert_verifier.
905     ///
906     /// # Example
907     ///
908     /// ```
909     /// use ylong_http_client::async_impl::ClientBuilder;
910     /// use ylong_http_client::{CertVerifier, ServerCerts};
911     ///
912     /// pub struct CallbackTest {
913     ///     inner: String,
914     /// }
915     ///
916     /// impl CallbackTest {
917     ///     pub(crate) fn new() -> Self {
918     ///         Self {
919     ///             inner: "Test".to_string(),
920     ///         }
921     ///     }
922     /// }
923     ///
924     /// impl CertVerifier for CallbackTest {
925     ///     fn verify(&self, certs: &ServerCerts) -> bool {
926     ///         true
927     ///     }
928     /// }
929     ///
930     /// let verifier = CallbackTest::new();
931     /// let builder = ClientBuilder::new().cert_verifier(verifier);
932     /// ```
cert_verifiernull933     pub fn cert_verifier<T: CertVerifier + Send + Sync + 'static>(mut self, verifier: T) -> Self {
934         use crate::util::config::tls::DefaultCertVerifier;
935 
936         self.tls = self
937             .tls
938             .cert_verifier(Arc::new(DefaultCertVerifier::new(verifier)));
939         self
940     }
941 }
942 
943 impl Default for ClientBuilder {
defaultnull944     fn default() -> Self {
945         Self::new()
946     }
947 }
948 
949 #[cfg(test)]
950 mod ut_async_impl_client {
951     #[cfg(feature = "ylong_base")]
952     use ylong_runtime::io::AsyncWriteExt;
953 
954     #[cfg(feature = "ylong_base")]
955     use crate::async_impl::{Body, Request, Response};
956     use crate::async_impl::{Client, HttpConnector};
957     #[cfg(feature = "ylong_base")]
958     use crate::util::test_utils::{format_header_str, TcpHandle};
959     #[cfg(feature = "ylong_base")]
960     use crate::{build_client_request, start_tcp_server, Retry};
961     #[cfg(all(feature = "__tls", feature = "ylong_base"))]
962     use crate::{CertVerifier, ServerCerts};
963     #[cfg(feature = "__tls")]
964     use crate::{Certificate, TlsVersion};
965     use crate::{Proxy, Timeout};
966 
967     #[cfg(all(feature = "__tls", feature = "ylong_base"))]
968     struct Verifier;
969 
970     #[cfg(feature = "ylong_base")]
971     async fn client_request_redirect() {
972         use std::sync::Arc;
973 
974         use ylong_http::h1::ResponseDecoder;
975         use ylong_http::response::Response as HttpResponse;
976 
977         use crate::async_impl::interceptor::IdleInterceptor;
978         use crate::async_impl::{ClientBuilder, HttpBody};
979         use crate::util::normalizer::BodyLength;
980         use crate::util::request::RequestArc;
981         use crate::util::Redirect;
982 
983         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();
984         let mut decoder = ResponseDecoder::new();
985         let result = decoder.decode(response_str).unwrap().unwrap();
986 
987         let box_stream = Box::new("hello world".as_bytes());
988         let content_bytes = "";
989         let until_close = HttpBody::new(
990             Arc::new(IdleInterceptor),
991             BodyLength::UntilClose,
992             box_stream,
993             content_bytes.as_bytes(),
994         )
995         .unwrap();
996         let response = HttpResponse::from_raw_parts(result.0, until_close);
997         let response = Response::new(response);
998         let request = Request::builder()
999             .url("http://example1.com:80/foo?a=1")
1000             .body(Body::slice("this is a body"))
1001             .unwrap();
1002         let request = RequestArc::new(request);
1003 
1004         let client = ClientBuilder::default()
1005             .redirect(Redirect::limited(2))
1006             .connect_timeout(Timeout::from_secs(2))
1007             .build()
1008             .unwrap();
1009         let res = client.redirect(response, request.clone()).await;
1010         assert!(res.is_ok())
1011     }
1012 
1013     #[cfg(feature = "ylong_base")]
1014     async fn client_request_version_1_0() {
1015         let request = Request::builder()
1016             .url("http://example1.com:80/foo?a=1")
1017             .method("CONNECT")
1018             .version("HTTP/1.0")
1019             .body(Body::empty())
1020             .unwrap();
1021 
1022         let client = Client::builder().http1_only().build().unwrap();
1023         let res = client.request(request).await;
1024         assert!(res
1025             .map_err(|e| {
1026                 assert_eq!(format!("{e}"), "Request Error: Unknown METHOD in HTTP/1.0");
1027                 e
1028             })
1029             .is_err());
1030     }
1031 
1032     #[cfg(all(feature = "__tls", feature = "ylong_base"))]
1033     impl CertVerifier for Verifier {
verifynull1034         fn verify(&self, certs: &ServerCerts) -> bool {
1035             // get version
1036             let _v = certs.version().unwrap();
1037             // get issuer
1038             let _i = certs.issuer().unwrap();
1039             // get name
1040             let _n = certs.cert_name().unwrap();
1041             // cmp cert file
1042             let cert_pem = r#"-----BEGIN CERTIFICATE-----
1043 MIIDGzCCAgMCCQCHcfe97pgvpTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB
1044 VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
1045 cyBQdHkgTHRkMB4XDTE2MDgxNDE3MDAwM1oXDTI2MDgxMjE3MDAwM1owWjELMAkG
1046 A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0
1047 IFdpZGdpdHMgUHR5IEx0ZDETMBEGA1UEAwwKZm9vYmFyLmNvbTCCASIwDQYJKoZI
1048 hvcNAQEBBQADggEPADCCAQoCggEBAKj0JYxEsxejUIX+I5GH0Hg2G0kX/y1H0+Ub
1049 3mw2/Ja5BD/yN96/7zMSumXF8uS3SkmpyiJkbyD01TSRTqjlP7/VCBlyUIChlpLQ
1050 mrGaijZiT/VCyPXqmcwFzXS5IOTpX1olJfW8rA41U1LCIcDUyFf6LtZ/v8rSeKr6
1051 TuE6SGV4WRaBm1SrjWBeHVV866CRrtSS1ieT2asFsAyOZqWhk2fakwwBDFWDhOGI
1052 ubfO+5aq9cBJbNRlzsgB3UZs3gC0O6GzbnZ6oT0TiJMeTsXXjABLUlaq/rrqFF4Y
1053 euZkkbHTFBMz288PUc3m3ZTcpN+E7+ZOUBRZXKD20K07NugqCzUCAwEAATANBgkq
1054 hkiG9w0BAQsFAAOCAQEASvYHuIl5C0NHBELPpVHNuLbQsDQNKVj3a54+9q1JkiMM
1055 6taEJYfw7K1Xjm4RoiFSHpQBh+PWZS3hToToL2Zx8JfMR5MuAirdPAy1Sia/J/qE
1056 wQdJccqmvuLkLTSlsGbEJ/LUUgOAgrgHOZM5lUgIhCneA0/dWJ3PsN0zvn69/faY
1057 oo1iiolWiIHWWBUSdr3jM2AJaVAsTmLh00cKaDNk37JB940xConBGSl98JPrNrf9
1058 dUAiT0iIBngDBdHnn/yTj+InVEFyZSKrNtiDSObFHxPcxGteHNrCPJdP1e+GqkHp
1059 HJMRZVCQpSMzvHlofHSNgzWV1MX5h1CP4SGZdBDTfA==
1060 -----END CERTIFICATE-----"#;
1061             let _c = certs.cmp_pem_cert(cert_pem.as_bytes()).unwrap();
1062             false
1063         }
1064     }
1065 
1066     #[cfg(all(feature = "__tls", feature = "ylong_base"))]
1067     async fn client_request_verify() {
1068         // Creates a `async_impl::Client`
1069         let client = Client::builder().cert_verifier(Verifier).build().unwrap();
1070         // Creates a `Request`.
1071         let request = Request::builder()
1072             .url("https://www.example.com")
1073             .body(Body::empty())
1074             .unwrap();
1075         // Sends request and receives a `Response`.
1076         let response = client.request(request).await;
1077         assert!(response.is_err())
1078     }
1079 
1080     /// UT test cases for `Client::builder`.
1081     ///
1082     /// # Brief
1083     /// 1. Creates a ClientBuilder by calling `Client::Builder`.
1084     /// 2. Calls `http_config`, `client_config`, `build` on the builder
1085     ///    respectively.
1086     /// 3. Checks if the result is as expected.
1087     #[cfg(feature = "http1_1")]
1088     #[test]
ut_client_buildernull1089     fn ut_client_builder() {
1090         let builder = Client::builder().http1_only().build();
1091         assert!(builder.is_ok());
1092         let builder_proxy = Client::builder()
1093             .proxy(Proxy::http("http://www.example.com").build().unwrap())
1094             .build();
1095         assert!(builder_proxy.is_ok());
1096     }
1097 
1098     /// UT test cases for `Client::with_connector`.
1099     ///
1100     /// # Brief
1101     /// 1. Creates a Client by calling `Client::with_connector`.
1102     /// 2. Checks if the result is as expected.
1103     #[test]
ut_client_with_connectornull1104     fn ut_client_with_connector() {
1105         let client = Client::with_connector(HttpConnector::default());
1106         assert_eq!(client.config.connect_timeout, Timeout::none())
1107     }
1108 
1109     /// UT test cases for `Client::new`.
1110     ///
1111     /// # Brief
1112     /// 1. Creates a Client by calling `Client::new`.
1113     /// 2. Checks if the result is as expected.
1114     #[test]
ut_client_newnull1115     fn ut_client_new() {
1116         let client = Client::new();
1117         assert_eq!(client.config.connect_timeout, Timeout::none())
1118     }
1119 
1120     /// UT test cases for `Client::default`.
1121     ///
1122     /// # Brief
1123     /// 1. Creates a Client by calling `Client::default`.
1124     /// 2. Checks if the result is as expected.
1125     #[test]
ut_client_defaultnull1126     fn ut_client_default() {
1127         let client = Client::default();
1128         assert_eq!(client.config.connect_timeout, Timeout::none())
1129     }
1130 
1131     /// UT test cases for `ClientBuilder::build`.
1132     ///
1133     /// # Brief
1134     /// 1. Creates a ClientBuilder by calling `Client::Builder`.
1135     /// 2. Checks if the result is as expected.
1136     #[cfg(feature = "__tls")]
1137     #[test]
ut_client_build_tlsnull1138     fn ut_client_build_tls() {
1139         let client = Client::builder()
1140             .max_tls_version(TlsVersion::TLS_1_3)
1141             .min_tls_version(TlsVersion::TLS_1_0)
1142             .add_root_certificate(Certificate::from_pem(b"cert").unwrap())
1143             .tls_ca_file("ca.crt")
1144             .tls_cipher_list(
1145                 "DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK",
1146             )
1147             .tls_built_in_root_certs(false)
1148             .danger_accept_invalid_certs(false)
1149             .danger_accept_invalid_hostnames(false)
1150             .tls_sni(false)
1151             .build();
1152 
1153         assert!(client.is_err());
1154     }
1155 
1156     /// UT test cases for `ClientBuilder::build`.
1157     ///
1158     /// # Brief
1159     /// 1. Creates a ClientBuilder by calling `Client::Builder`.
1160     /// 2. Checks if the result is as expected.
1161     #[cfg(feature = "__tls")]
1162     #[test]
ut_client_build_tls_pubkey_pinningnull1163     fn ut_client_build_tls_pubkey_pinning() {
1164         use crate::PubKeyPins;
1165 
1166         let client = Client::builder()
1167             .tls_built_in_root_certs(true) // not use root certs
1168             .danger_accept_invalid_certs(true) // not verify certs
1169             .max_tls_version(TlsVersion::TLS_1_2)
1170             .min_tls_version(TlsVersion::TLS_1_2)
1171             .add_public_key_pins(
1172                 PubKeyPins::builder()
1173                     .add(
1174                         "https://7.249.243.101:6789",
1175                         "sha256//VHQAbNl67nmkZJNESeTKvTxb5bQmd1maWnMKG/tjcAY=",
1176                     )
1177                     .build()
1178                     .unwrap(),
1179             )
1180             .build();
1181         assert!(client.is_ok())
1182     }
1183 
1184     /// UT test cases for `ClientBuilder::default`.
1185     ///
1186     /// # Brief
1187     /// 1. Creates a `ClientBuilder` by calling `ClientBuilder::default`.
1188     /// 2. Calls `http_config`, `client_config`, `tls_config` and `build`
1189     ///    respectively.
1190     /// 3. Checks if the result is as expected.
1191     #[test]
ut_client_builder_defaultnull1192     fn ut_client_builder_default() {
1193         use crate::async_impl::ClientBuilder;
1194         use crate::util::{Redirect, Timeout};
1195 
1196         let builder = ClientBuilder::default()
1197             .redirect(Redirect::none())
1198             .connect_timeout(Timeout::from_secs(9))
1199             .build();
1200         assert!(builder.is_ok())
1201     }
1202 
1203     /// UT test cases for `ClientBuilder::default`.
1204     ///
1205     /// # Brief
1206     /// 1. Creates a `ClientBuilder` by calling `ClientBuilder::default`.
1207     /// 2. Set redirect for client and call `Client::redirect_request`.
1208     /// 3. Checks if the result is as expected.
1209     #[cfg(feature = "ylong_base")]
1210     #[test]
ut_client_request_redirectnull1211     fn ut_client_request_redirect() {
1212         let handle = ylong_runtime::spawn(async move {
1213             client_request_redirect().await;
1214         });
1215         ylong_runtime::block_on(handle).unwrap();
1216     }
1217 
1218     /// UT test cases for `Client::request`.
1219     ///
1220     /// # Brief
1221     /// 1. Creates a `Client` by calling `Client::builder()`.
1222     /// 2. Set version HTTP/1.0 for client and call `Client::request`.
1223     /// 3. Checks if the result is as expected.
1224     #[cfg(feature = "ylong_base")]
1225     #[test]
ut_client_connect_http1_0null1226     fn ut_client_connect_http1_0() {
1227         let handle = ylong_runtime::spawn(async move {
1228             client_request_version_1_0().await;
1229         });
1230         ylong_runtime::block_on(handle).unwrap();
1231     }
1232 
1233     /// UT test cases for retry of `Client::request`.
1234     ///
1235     /// # Brief
1236     /// 1. Creates a `Client` by calling `Client::builder()`.
1237     /// 2. Set version HTTP/1.0 for client and call `Client::request`.
1238     /// 3. Checks if the result is as expected.
1239     #[cfg(feature = "ylong_base")]
1240     #[test]
ut_client_request_http1_0_retrynull1241     fn ut_client_request_http1_0_retry() {
1242         let request = Request::builder()
1243             .url("http://example1.com:80/foo?a=1")
1244             .method("CONNECT")
1245             .version("HTTP/1.0")
1246             .body(Body::empty())
1247             .unwrap();
1248 
1249         let retry_times = Retry::new(1).unwrap();
1250         let client = Client::builder()
1251             .retry(retry_times)
1252             .http1_only()
1253             .build()
1254             .unwrap();
1255 
1256         let handle = ylong_runtime::spawn(async move {
1257             let res = client.request(request).await;
1258             assert!(res
1259                 .map_err(|e| {
1260                     assert_eq!(format!("{e}"), "Request Error: Unknown METHOD in HTTP/1.0");
1261                     e
1262                 })
1263                 .is_err());
1264         });
1265         ylong_runtime::block_on(handle).unwrap();
1266     }
1267 
1268     /// UT test cases for certificate verify of `Client::request`.
1269     ///
1270     /// # Brief
1271     /// 1. Creates a `Client` by calling `Client::builder()`.
1272     /// 2. implement `CertVerifier` for struct `Verifier`.
1273     /// 3. Sets `CertVerifier` for this client.
1274     /// 4. Checks if the result is as expected.
1275     #[cfg(all(feature = "__tls", feature = "ylong_base"))]
1276     #[test]
ut_client_request_verifynull1277     fn ut_client_request_verify() {
1278         let handle = ylong_runtime::spawn(async move {
1279             client_request_verify().await;
1280         });
1281         ylong_runtime::block_on(handle).unwrap();
1282     }
1283 
1284     /// UT test cases for certificate verify of `Client::send_request`.
1285     ///
1286     /// # Brief
1287     /// 1. Creates a `Client` by calling `Client::builder()`.
1288     /// 2. Sends a `Request` by `Client::send_request`.
1289     /// 4. Checks if the result is as expected.
1290     #[cfg(feature = "ylong_base")]
1291     #[test]
ut_client_send_requestnull1292     fn ut_client_send_request() {
1293         let mut handles = vec![];
1294         start_tcp_server!(
1295            Handles: handles,
1296            Response: {
1297                Status: 201,
1298                Version: "HTTP/1.1",
1299                Header: "Content-Length", "11",
1300                Body: "METHOD GET!",
1301            },
1302         );
1303         let handle = handles.pop().expect("No more handles !");
1304 
1305         let request = build_client_request!(
1306             Request: {
1307                 Method: "GET",
1308                 Path: "/data",
1309                 Addr: handle.addr.as_str(),
1310                 Header: "Content-Length", "5",
1311                 Body: Body::slice("HELLO".as_bytes()),
1312             },
1313         );
1314         let client = Client::builder()
1315             .connect_timeout(Timeout::from_secs(2))
1316             .http1_only()
1317             .build()
1318             .unwrap();
1319 
1320         let handle = ylong_runtime::spawn(async move {
1321             let resp = client.request(request).await;
1322             assert!(resp.is_ok());
1323             let body = resp.unwrap().text().await;
1324             assert!(body.is_ok());
1325             handle
1326                 .server_shutdown
1327                 .recv()
1328                 .expect("server send order failed !");
1329         });
1330         ylong_runtime::block_on(handle).unwrap();
1331     }
1332 
1333     /// UT test cases for retry of `Client::connect_to`.
1334     ///
1335     /// # Brief
1336     /// 1. Creates a `Client` by calling `Client::builder()`.
1337     /// 2. Sets connect timeout for this client.
1338     /// 3. Checks if the result is as expected.
1339     #[cfg(feature = "ylong_base")]
1340     #[test]
ut_client_connect_tonull1341     fn ut_client_connect_to() {
1342         let client = Client::builder()
1343             .connect_timeout(Timeout::from_secs(1))
1344             .http1_only()
1345             .build()
1346             .unwrap();
1347 
1348         let request = build_client_request!(
1349             Request: {
1350                 Path: "",
1351                 Addr: "198.18.0.25:80",
1352                 Body: Body::empty(),
1353             },
1354         );
1355         let handle = ylong_runtime::spawn(async move {
1356             let res = client.request(request).await;
1357             assert!(res.is_err());
1358         });
1359         ylong_runtime::block_on(handle).unwrap();
1360     }
1361 
1362     /// UT test cases for certificate verify of `Client::redirect`.
1363     ///
1364     /// # Brief
1365     /// 1. Creates a `Client` by calling `Client::builder()`.
1366     /// 2. Sends a `Request` by `Client::redirect`.
1367     /// 3. Checks if the result is as expected.
1368     #[cfg(feature = "ylong_base")]
1369     #[test]
ut_client_redirectnull1370     fn ut_client_redirect() {
1371         let mut handles = vec![];
1372         start_tcp_server!(
1373            Handles: handles,
1374            Response: {
1375                Status: 302,
1376                Version: "HTTP/1.1",
1377                Header: "Content-Length", "11",
1378                Header: "Location", "http://ylong_http.com:80",
1379                Body: "METHOD GET!",
1380            },
1381         );
1382         let handle = handles.pop().expect("No more handles !");
1383 
1384         let request = build_client_request!(
1385             Request: {
1386                 Method: "GET",
1387                 Path: "/data",
1388                 Addr: handle.addr.as_str(),
1389                 Header: "Content-Length", "5",
1390                 Body: Body::slice("HELLO".as_bytes()),
1391             },
1392         );
1393         let client = Client::builder()
1394             .request_timeout(Timeout::from_secs(2))
1395             .http1_only()
1396             .build()
1397             .unwrap();
1398 
1399         let handle = ylong_runtime::spawn(async move {
1400             let resp = client.request(request).await;
1401             assert!(resp.is_err());
1402             handle
1403                 .server_shutdown
1404                 .recv()
1405                 .expect("server send order failed !");
1406         });
1407         ylong_runtime::block_on(handle).unwrap();
1408     }
1409 
1410     /// UT test cases for proxy of `Client::request`.
1411     ///
1412     /// # Brief
1413     /// 1. Creates a `Client` by calling `Client::builder()`.
1414     /// 2. Sends a `Request` by `Client::request`.
1415     /// 3. Checks if the result is as expected.
1416     #[cfg(feature = "ylong_base")]
1417     #[test]
ut_client_http_proxynull1418     fn ut_client_http_proxy() {
1419         let mut handles = vec![];
1420         start_tcp_server!(
1421            Handles: handles,
1422            Response: {
1423                Status: 201,
1424                Version: "HTTP/1.1",
1425                Header: "Content-Length", "11",
1426                Body: "METHOD GET!",
1427            },
1428         );
1429         let handle = handles.pop().expect("No more handles !");
1430 
1431         let request = build_client_request!(
1432             Request: {
1433                 Method: "GET",
1434                 Path: "/data",
1435                 Addr: "ylong_http.com",
1436                 Header: "Content-Length", "5",
1437                 Body: Body::slice("HELLO".as_bytes()),
1438             },
1439         );
1440         let client = Client::builder()
1441             .proxy(
1442                 Proxy::http(format!("http://{}{}", handle.addr.as_str(), "/data").as_str())
1443                     .build()
1444                     .expect("Http proxy build failed"),
1445             )
1446             .build()
1447             .expect("Client build failed!");
1448 
1449         let handle = ylong_runtime::spawn(async move {
1450             let resp = client.request(request).await;
1451             assert!(resp.is_ok());
1452             handle
1453                 .server_shutdown
1454                 .recv()
1455                 .expect("server send order failed !");
1456         });
1457         ylong_runtime::block_on(handle).unwrap();
1458     }
1459 
1460     /// UT test cases for sends chunk body of `Client::request`.
1461     ///
1462     /// # Brief
1463     /// 1. Creates a `Client` by calling `Client::builder()`.
1464     /// 2. Sends a `Request` by `Client::request`.
1465     /// 3. Checks if the result is as expected.
1466     #[cfg(feature = "ylong_base")]
1467     #[test]
ut_client_send_trunk_bodynull1468     fn ut_client_send_trunk_body() {
1469         let mut handles = vec![];
1470         start_tcp_server!(
1471            Handles: handles,
1472            Response: {
1473                Status: 201,
1474                Version: "HTTP/1.1",
1475                Header: "Content-Length", "11",
1476                Body: "METHOD GET!",
1477            },
1478         );
1479         let handle = handles.pop().expect("No more handles !");
1480 
1481         let request = build_client_request!(
1482             Request: {
1483                 Method: "GET",
1484                 Path: "/data",
1485                 Addr: handle.addr.as_str(),
1486                 Header: "Transfer-Encoding", "chunked",
1487                 Body: Body::slice("aaaaa bbbbb ccccc ddddd".as_bytes()),
1488             },
1489         );
1490         let client = Client::builder().http1_only().build().unwrap();
1491 
1492         let handle = ylong_runtime::spawn(async move {
1493             let resp = client.request(request).await;
1494             assert!(resp.is_ok());
1495             handle
1496                 .server_shutdown
1497                 .recv()
1498                 .expect("server send order failed !");
1499         });
1500         ylong_runtime::block_on(handle).unwrap();
1501     }
1502 
1503     /// UT test cases for sends no headers request of `Client::request`.
1504     ///
1505     /// # Brief
1506     /// 1. Creates a `Client` by calling `Client::builder()`.
1507     /// 2. Sends a `Request` by `Client::request`.
1508     /// 3. Checks if the result is as expected.
1509     #[cfg(feature = "ylong_base")]
1510     #[test]
ut_client_send_unknown_sizenull1511     fn ut_client_send_unknown_size() {
1512         let mut handles = vec![];
1513         start_tcp_server!(
1514            Handles: handles,
1515            Response: {
1516                Status: 201,
1517                Version: "HTTP/1.1",
1518                Header: "Content-Length", "11",
1519                Body: "METHOD GET!",
1520            },
1521         );
1522         let handle = handles.pop().expect("No more handles !");
1523 
1524         let request = build_client_request!(
1525             Request: {
1526                 Method: "GET",
1527                 Path: "/data",
1528                 Addr: handle.addr.as_str(),
1529                 Body: Body::empty(),
1530             },
1531         );
1532         let client = Client::builder().http1_only().build().unwrap();
1533 
1534         let handle = ylong_runtime::spawn(async move {
1535             let resp = client.request(request).await;
1536             assert!(resp.is_ok());
1537             handle
1538                 .server_shutdown
1539                 .recv()
1540                 .expect("server send order failed !");
1541         });
1542         ylong_runtime::block_on(handle).unwrap();
1543     }
1544 
1545     /// UT test cases for receive `Connection` header response of
1546     /// `Client::request`.
1547     ///
1548     /// # Brief
1549     /// 1. Creates a `Client` by calling `Client::builder()`.
1550     /// 2. Sends a `Request` by `Client::request`.
1551     /// 3. Checks if the result is as expected.
1552     #[cfg(feature = "ylong_base")]
1553     #[test]
ut_client_recv_conn_closenull1554     fn ut_client_recv_conn_close() {
1555         let mut handles = vec![];
1556         start_tcp_server!(
1557            Handles: handles,
1558            Response: {
1559                Status: 201,
1560                Version: "HTTP/1.1",
1561                Header: "Content-Length", "11",
1562                Header: "Connection", "close",
1563                Body: "METHOD GET!",
1564            },
1565         );
1566         let handle = handles.pop().expect("No more handles !");
1567 
1568         let request = build_client_request!(
1569             Request: {
1570                 Method: "GET",
1571                 Path: "/data",
1572                 Addr: handle.addr.as_str(),
1573                 Header: "Content-Length", "5",
1574                 Body: Body::slice("HELLO".as_bytes()),
1575             },
1576         );
1577         let client = Client::builder().http1_only().build().unwrap();
1578 
1579         let handle = ylong_runtime::spawn(async move {
1580             let resp = client.request(request).await;
1581             assert!(resp.is_ok());
1582             handle
1583                 .server_shutdown
1584                 .recv()
1585                 .expect("server send order failed !");
1586         });
1587         ylong_runtime::block_on(handle).unwrap();
1588     }
1589 
1590     /// UT test cases for receive HTTP/1.0 response with invalid header of
1591     /// `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_recv_http1_0_respnull1599     fn ut_client_recv_http1_0_resp() {
1600         let mut handles = vec![];
1601         start_tcp_server!(
1602            Handles: handles,
1603            Response: {
1604                Status: 201,
1605                Version: "HTTP/1.0",
1606                Header: "Content-Length", "11",
1607                Header: "Connection", "close",
1608                Body: "METHOD GET!",
1609            },
1610         );
1611         let handle = handles.pop().expect("No more handles !");
1612 
1613         let request = build_client_request!(
1614             Request: {
1615                 Method: "GET",
1616                 Version: "HTTP/1.0",
1617                 Path: "/data",
1618                 Addr: handle.addr.as_str(),
1619                 Header: "Content-Length", "5",
1620                 Body: Body::slice("HELLO".as_bytes()),
1621             },
1622         );
1623         let client = Client::builder().http1_only().build().unwrap();
1624 
1625         let handle = ylong_runtime::spawn(async move {
1626             let resp = client.request(request).await;
1627             assert!(resp.is_ok());
1628             handle
1629                 .server_shutdown
1630                 .recv()
1631                 .expect("server send order failed !");
1632         });
1633         ylong_runtime::block_on(handle).unwrap();
1634     }
1635 
1636     /// UT test cases for receive HTTP/1.0 response with transfer-encoding
1637     /// header of `Client::request`.
1638     ///
1639     /// # Brief
1640     /// 1. Creates a `Client` by calling `Client::builder()`.
1641     /// 2. Sends a `Request` by `Client::request`.
1642     /// 3. Checks if the result is as expected.
1643     #[cfg(feature = "ylong_base")]
1644     #[test]
ut_client_recv_invalid_http1_0_respnull1645     fn ut_client_recv_invalid_http1_0_resp() {
1646         let mut handles = vec![];
1647         start_tcp_server!(
1648            Handles: handles,
1649            Response: {
1650                Status: 201,
1651                Version: "HTTP/1.0",
1652                Header: "Transfer-Encoding", "chunked",
1653                Body: "0\r\n\r\n",
1654            },
1655         );
1656         let handle = handles.pop().expect("No more handles !");
1657 
1658         let request = build_client_request!(
1659             Request: {
1660                 Method: "GET",
1661                 Version: "HTTP/1.0",
1662                 Path: "/data",
1663                 Addr: handle.addr.as_str(),
1664                 Header: "Content-Length", "5",
1665                 Body: Body::slice("HELLO".as_bytes()),
1666             },
1667         );
1668         let client = Client::builder().http1_only().build().unwrap();
1669 
1670         let handle = ylong_runtime::spawn(async move {
1671             let resp = client.request(request).await;
1672             assert!(resp.is_err());
1673             handle
1674                 .server_shutdown
1675                 .recv()
1676                 .expect("server send order failed !");
1677         });
1678         ylong_runtime::block_on(handle).unwrap();
1679     }
1680 
1681     /// UT test cases for receive response when server is shutdown of
1682     /// `Client::request`.
1683     ///
1684     /// # Brief
1685     /// 1. Creates a `Client` by calling `Client::builder()`.
1686     /// 2. Sends a `Request` by `Client::request`.
1687     /// 3. Checks if the result is as expected.
1688     #[cfg(feature = "ylong_base")]
1689     #[test]
ut_client_recv_when_server_shutdownnull1690     fn ut_client_recv_when_server_shutdown() {
1691         let mut handles = vec![];
1692         start_tcp_server!(Handles: handles, Shutdown: std::net::Shutdown::Both,);
1693         let handle = handles.pop().expect("No more handles !");
1694 
1695         let request = build_client_request!(
1696             Request: {
1697                 Method: "GET",
1698                 Path: "/data",
1699                 Addr: handle.addr.as_str(),
1700                 Header: "Content-Length", "5",
1701                 Body: Body::slice("HELLO".as_bytes()),
1702             },
1703         );
1704         let client = Client::builder().http1_only().build().unwrap();
1705 
1706         let handle = ylong_runtime::spawn(async move {
1707             let resp = client.request(request).await;
1708             assert!(resp.is_err());
1709             handle
1710                 .server_shutdown
1711                 .recv()
1712                 .expect("server send order failed !");
1713         });
1714         ylong_runtime::block_on(handle).unwrap();
1715     }
1716 
1717     /// UT test cases for receive response status in error of `Client::request`.
1718     ///
1719     /// # Brief
1720     /// 1. Creates a `Client` by calling `Client::builder()`.
1721     /// 2. Sends a `Request` by `Client::request`.
1722     /// 3. Checks if the result is as expected.
1723     #[cfg(feature = "ylong_base")]
1724     #[test]
ut_client_recv_error_resp_statusnull1725     fn ut_client_recv_error_resp_status() {
1726         let mut handles = vec![];
1727         start_tcp_server!(
1728            Handles: handles,
1729            Response: {
1730                Status: 2023,
1731                Version: "HTTP/1.1",
1732                Header: "Content-Length", "11",
1733                Header: "Connection", "close",
1734                Body: "METHOD GET!",
1735            },
1736         );
1737         let handle = handles.pop().expect("No more handles !");
1738 
1739         let request = build_client_request!(
1740             Request: {
1741                 Method: "GET",
1742                 Path: "/data",
1743                 Addr: handle.addr.as_str(),
1744                 Header: "Content-Length", "5",
1745                 Body: Body::slice("HELLO".as_bytes()),
1746             },
1747         );
1748         let client = Client::builder().http1_only().build().unwrap();
1749 
1750         let handle = ylong_runtime::spawn(async move {
1751             let resp = client.request(request).await;
1752             assert!(resp.is_err());
1753             handle
1754                 .server_shutdown
1755                 .recv()
1756                 .expect("server send order failed !");
1757         });
1758         ylong_runtime::block_on(handle).unwrap();
1759     }
1760 }
1761