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