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