qiniu_http_client/client/
http_client.rs

1use super::{
2    super::{EndpointsProvider, IpAddrWithPort, ServiceName},
3    callbacks::{Callbacks, CallbacksBuilder},
4    Backoff, CachedResolver, CallbackContext, ChainedResolver, Chooser, ErrorRetrier, ExponentialBackoff,
5    ExtendedCallbackContext, LimitedBackoff, LimitedRetrier, NeverEmptyHandedChooser, RandomizedBackoff,
6    RequestRetrier, ResolveAnswers, Resolver, ResponseError, ShuffledChooser, ShuffledResolver, SimpleResolver,
7    SimplifiedCallbackContext, SubnetChooser, SyncRequestBuilder, TimeoutResolver,
8};
9use anyhow::Result as AnyResult;
10use assert_impl::assert_impl;
11use cfg_if::cfg_if;
12use qiniu_http::{
13    HeaderName, HeaderValue, HttpCaller, Method, ResponseParts, StatusCode, TransferProgressInfo, UserAgent,
14};
15use std::{
16    mem::{replace, take},
17    sync::Arc,
18    time::Duration,
19};
20
21#[cfg(feature = "isahc")]
22use qiniu_isahc::isahc::error::Error as IsahcError;
23
24#[cfg(feature = "async")]
25use super::AsyncRequestBuilder;
26
27/// HTTP 客户端
28///
29/// 用于发送 HTTP 请求的入口。
30///
31/// 其中 HTTP 请求将由 [`HttpCaller`] 实现的实例来发送,如果不指定,默认通过当前启用的功能来判定。
32///
33/// ### 私有云获取当前账户的 Buckets 列表
34///
35/// ##### 阻塞代码示例
36///
37/// ```
38/// use qiniu_credential::Credential;
39/// use qiniu_http_client::{Authorization, HttpClient, Region, RegionsProviderEndpoints, ServiceName};
40///
41/// # fn example() -> anyhow::Result<()> {
42/// let region = Region::builder("z0")
43///     .add_uc_preferred_endpoint("uc-qos.pocdemo.qiniu.io".parse()?)
44///     .build();
45/// let credential = Credential::new("abcdefghklmnopq", "1234567890");
46/// let bucket_names: Vec<String> = HttpClient::default()
47///     .get(&[ServiceName::Uc], RegionsProviderEndpoints::new(region))
48///     .use_https(false)
49///     .authorization(Authorization::v2(credential))
50///     .accept_json()
51///     .path("/buckets")
52///     .call()?
53///     .parse_json()?
54///     .into_body();
55/// # Ok(())
56/// # }
57/// ```
58///
59/// ##### 异步代码示例
60///
61/// ```
62/// use qiniu_credential::Credential;
63/// use qiniu_http_client::{Authorization, HttpClient, Region, RegionsProviderEndpoints, ServiceName};
64///
65/// # async fn example() -> anyhow::Result<()> {
66/// let region = Region::builder("z0")
67///     .add_uc_preferred_endpoint("uc-qos.pocdemo.qiniu.io".parse()?)
68///     .build();
69/// let credential = Credential::new("abcdefghklmnopq", "1234567890");
70/// let bucket_names: Vec<String> = HttpClient::default()
71///     .async_get(&[ServiceName::Uc], RegionsProviderEndpoints::new(region))
72///     .use_https(false)
73///     .authorization(Authorization::v2(credential))
74///     .accept_json()
75///     .path("/buckets")
76///     .call()
77///     .await?
78///     .parse_json()
79///     .await?
80///     .into_body();
81/// # Ok(())
82/// # }
83/// ```
84#[derive(Debug, Clone)]
85pub struct HttpClient {
86    inner: Arc<HttpClientInner>,
87}
88
89impl HttpClient {
90    #[allow(dead_code)]
91    fn assert() {
92        assert_impl!(Send: Self);
93        assert_impl!(Sync: Self);
94    }
95}
96
97#[derive(Debug)]
98struct HttpClientInner {
99    use_https: bool,
100    appended_user_agent: UserAgent,
101    http_caller: Box<dyn HttpCaller>,
102    request_retrier: Box<dyn RequestRetrier>,
103    backoff: Box<dyn Backoff>,
104    chooser: Box<dyn Chooser>,
105    resolver: Box<dyn Resolver>,
106    callbacks: Callbacks<'static>,
107}
108
109impl HttpClient {
110    /// 创建一个新的 HTTP 客户端,使用 [`crate::ureq::Client`] 作为 [`HttpCaller`] 实现
111    #[inline]
112    #[cfg(feature = "ureq")]
113    #[cfg_attr(feature = "docs", doc(cfg(feature = "ureq")))]
114    pub fn ureq() -> Self {
115        Self::build_ureq().build()
116    }
117
118    /// 创建一个新的 HTTP 客户端,使用 [`crate::isahc::Client`] 作为 [`HttpCaller`] 实现
119    #[inline]
120    #[cfg(feature = "isahc")]
121    #[cfg_attr(feature = "docs", doc(cfg(feature = "isahc")))]
122    pub fn isahc() -> Result<Self, IsahcError> {
123        Ok(Self::build_isahc()?.build())
124    }
125
126    /// 创建一个新的 HTTP 客户端,使用 [`crate::reqwest::SyncClient`] 作为 [`HttpCaller`] 实现
127    #[inline]
128    #[cfg(feature = "reqwest")]
129    #[cfg_attr(feature = "docs", doc(cfg(feature = "reqwest")))]
130    pub fn reqwest_sync() -> Self {
131        Self::build_reqwest_sync().build()
132    }
133
134    /// 创建一个新的 HTTP 客户端,使用 [`crate::reqwest::AsyncClient`] 作为 [`HttpCaller`] 实现
135    #[inline]
136    #[cfg(all(feature = "reqwest", feature = "async"))]
137    #[cfg_attr(feature = "docs", doc(cfg(all(feature = "reqwest", feature = "async"))))]
138    pub fn reqwest_async() -> Self {
139        Self::build_reqwest_async().build()
140    }
141
142    /// 创建一个新的 HTTP 客户端,根据当前环境变量选择 [`HttpCaller`] 实现
143    #[inline]
144    pub fn build_default() -> HttpClientBuilder {
145        HttpClientBuilder::default()
146    }
147
148    /// 创建一个新的 HTTP 客户端构建器,使用 [`crate::ureq::Client`] 作为 [`HttpCaller`] 实现
149    #[inline]
150    #[cfg(feature = "ureq")]
151    #[cfg_attr(feature = "docs", doc(cfg(feature = "ureq")))]
152    pub fn build_ureq() -> HttpClientBuilder {
153        HttpClientBuilder::ureq()
154    }
155
156    /// 创建一个新的 HTTP 客户端构建器,使用 [`crate::isahc::Client`] 作为 [`HttpCaller`] 实现
157    #[inline]
158    #[cfg(feature = "isahc")]
159    #[cfg_attr(feature = "docs", doc(cfg(feature = "isahc")))]
160    pub fn build_isahc() -> Result<HttpClientBuilder, IsahcError> {
161        HttpClientBuilder::isahc()
162    }
163
164    /// 创建一个新的 HTTP 客户端构建器,使用 [`crate::reqwest::SyncClient`] 作为 [`HttpCaller`] 实现
165    #[inline]
166    #[cfg(feature = "reqwest")]
167    #[cfg_attr(feature = "docs", doc(cfg(feature = "reqwest")))]
168    pub fn build_reqwest_sync() -> HttpClientBuilder {
169        HttpClientBuilder::reqwest_sync()
170    }
171
172    /// 创建一个新的 HTTP 客户端构建器,使用 [`crate::reqwest::AsyncClient`] 作为 [`HttpCaller`] 实现
173    #[inline]
174    #[cfg(all(feature = "reqwest", feature = "async"))]
175    #[cfg_attr(feature = "docs", doc(cfg(all(feature = "reqwest", feature = "async"))))]
176    pub fn build_reqwest_async() -> HttpClientBuilder {
177        HttpClientBuilder::reqwest_async()
178    }
179
180    /// 创建一个新的 HTTP 客户端,需要指定 [`HttpCaller`] 实现
181    #[inline]
182    pub fn new(http_caller: impl HttpCaller + 'static) -> Self {
183        HttpClientBuilder::new(http_caller).build()
184    }
185
186    /// 创建一个新的 HTTP 客户端构建器,需要指定 [`HttpCaller`] 实现
187    #[inline]
188    pub fn builder(http_caller: impl HttpCaller + 'static) -> HttpClientBuilder {
189        HttpClientBuilder::new(http_caller)
190    }
191
192    /// 创建 GET 请求的请求构建器
193    ///
194    /// 该方法的异步版本为 [`HttpClient::async_get`]。
195    #[inline]
196    pub fn get<'r, E: EndpointsProvider + 'r>(
197        &'r self,
198        service_names: &'r [ServiceName],
199        endpoints_provider: E,
200    ) -> SyncRequestBuilder<'r, E> {
201        self.new_request(Method::GET, service_names, endpoints_provider)
202    }
203
204    /// 创建 POST 请求的请求构建器
205    ///
206    /// 该方法的异步版本为 [`HttpClient::async_post`]。
207    #[inline]
208    pub fn post<'r, E: EndpointsProvider + 'r>(
209        &'r self,
210        service_names: &'r [ServiceName],
211        endpoints_provider: E,
212    ) -> SyncRequestBuilder<'r, E> {
213        self.new_request(Method::POST, service_names, endpoints_provider)
214    }
215
216    /// 创建 PUT 请求的请求构建器
217    ///
218    /// 该方法的异步版本为 [`HttpClient::async_put`]。
219    #[inline]
220    pub fn put<'r, E: EndpointsProvider + 'r>(
221        &'r self,
222        service_names: &'r [ServiceName],
223        endpoints_provider: E,
224    ) -> SyncRequestBuilder<'r, E> {
225        self.new_request(Method::PUT, service_names, endpoints_provider)
226    }
227
228    /// 创建 DELETE 请求的请求构建器
229    ///
230    /// 该方法的异步版本为 [`HttpClient::async_delete`]。
231    #[inline]
232    pub fn delete<'r, E: EndpointsProvider + 'r>(
233        &'r self,
234        service_names: &'r [ServiceName],
235        endpoints_provider: E,
236    ) -> SyncRequestBuilder<'r, E> {
237        self.new_request(Method::DELETE, service_names, endpoints_provider)
238    }
239
240    /// 创建请求的请求构建器
241    ///
242    /// 该方法的异步版本为 [`HttpClient::new_async_request`]。
243    #[inline]
244    pub fn new_request<'r, E: EndpointsProvider + 'r>(
245        &'r self,
246        method: Method,
247        service_names: &'r [ServiceName],
248        endpoints_provider: E,
249    ) -> SyncRequestBuilder<'r, E> {
250        SyncRequestBuilder::new(self, method, endpoints_provider, service_names)
251    }
252
253    /// 创建 GET 请求的异步请求构建器
254    #[inline]
255    #[cfg(feature = "async")]
256    #[cfg_attr(feature = "docs", doc(cfg(feature = "async")))]
257    pub fn async_get<'r, E: EndpointsProvider + 'r>(
258        &'r self,
259        service_names: &'r [ServiceName],
260        endpoints_provider: E,
261    ) -> AsyncRequestBuilder<'r, E> {
262        self.new_async_request(Method::GET, service_names, endpoints_provider)
263    }
264
265    /// 创建 POST 请求的异步请求构建器
266    #[inline]
267    #[cfg(feature = "async")]
268    #[cfg_attr(feature = "docs", doc(cfg(feature = "async")))]
269    pub fn async_post<'r, E: EndpointsProvider + 'r>(
270        &'r self,
271        service_names: &'r [ServiceName],
272        endpoints_provider: E,
273    ) -> AsyncRequestBuilder<'r, E> {
274        self.new_async_request(Method::POST, service_names, endpoints_provider)
275    }
276
277    /// 创建 PUT 请求的异步请求构建器
278    #[inline]
279    #[cfg(feature = "async")]
280    #[cfg_attr(feature = "docs", doc(cfg(feature = "async")))]
281    pub fn async_put<'r, E: EndpointsProvider + 'r>(
282        &'r self,
283        service_names: &'r [ServiceName],
284        endpoints_provider: E,
285    ) -> AsyncRequestBuilder<'r, E> {
286        self.new_async_request(Method::PUT, service_names, endpoints_provider)
287    }
288
289    /// 创建 DELETE 请求的异步请求构建器
290    #[inline]
291    #[cfg(feature = "async")]
292    #[cfg_attr(feature = "docs", doc(cfg(feature = "async")))]
293    pub fn async_delete<'r, E: EndpointsProvider + 'r>(
294        &'r self,
295        service_names: &'r [ServiceName],
296        endpoints_provider: E,
297    ) -> AsyncRequestBuilder<'r, E> {
298        self.new_async_request(Method::DELETE, service_names, endpoints_provider)
299    }
300
301    /// 创建异步请求的请求构建器
302    #[cfg(feature = "async")]
303    pub fn new_async_request<'r, E: EndpointsProvider + 'r>(
304        &'r self,
305        method: Method,
306        service_names: &'r [ServiceName],
307        endpoints_provider: E,
308    ) -> AsyncRequestBuilder<'r, E> {
309        AsyncRequestBuilder::new(self, method, endpoints_provider, service_names)
310    }
311
312    pub(super) fn use_https(&self) -> bool {
313        self.inner.use_https
314    }
315
316    pub(super) fn appended_user_agent(&self) -> &UserAgent {
317        &self.inner.appended_user_agent
318    }
319
320    pub(super) fn callbacks(&self) -> &Callbacks<'static> {
321        &self.inner.callbacks
322    }
323
324    pub(super) fn http_caller(&self) -> &dyn HttpCaller {
325        self.inner.http_caller.as_ref()
326    }
327
328    pub(super) fn request_retrier(&self) -> &dyn RequestRetrier {
329        self.inner.request_retrier.as_ref()
330    }
331
332    pub(super) fn backoff(&self) -> &dyn Backoff {
333        self.inner.backoff.as_ref()
334    }
335
336    pub(super) fn chooser(&self) -> &dyn Chooser {
337        self.inner.chooser.as_ref()
338    }
339
340    pub(super) fn resolver(&self) -> &dyn Resolver {
341        self.inner.resolver.as_ref()
342    }
343}
344
345/// HTTP 客户端构建器
346#[derive(Debug)]
347pub struct HttpClientBuilder {
348    use_https: bool,
349    appended_user_agent: UserAgent,
350    http_caller: Option<Box<dyn HttpCaller>>,
351    request_retrier: Option<Box<dyn RequestRetrier>>,
352    backoff: Option<Box<dyn Backoff>>,
353    chooser: Option<Box<dyn Chooser>>,
354    resolver: Option<Box<dyn Resolver>>,
355    callbacks: CallbacksBuilder<'static>,
356}
357
358impl HttpClientBuilder {
359    /// 创建一个新的 HTTP 客户端构建器,使用 [`crate::ureq::Client`] 作为 [`HttpCaller`] 实现
360    #[inline]
361    #[cfg(feature = "ureq")]
362    pub fn ureq() -> Self {
363        Self::_new(Some(Box::<qiniu_ureq::Client>::default()))
364    }
365
366    /// 创建一个新的 HTTP 客户端构建器,使用 [`crate::isahc::Client`] 作为 [`HttpCaller`] 实现
367    #[inline]
368    #[cfg(feature = "isahc")]
369    pub fn isahc() -> Result<Self, IsahcError> {
370        Ok(Self::_new(Some(Box::new(qiniu_isahc::Client::default_client()?))))
371    }
372
373    /// 创建一个新的 HTTP 客户端构建器,使用 [`crate::reqwest::SyncClient`] 作为 [`HttpCaller`] 实现
374    #[inline]
375    #[cfg(feature = "reqwest")]
376    pub fn reqwest_sync() -> Self {
377        Self::_new(Some(Box::<qiniu_reqwest::SyncClient>::default()))
378    }
379
380    /// 创建一个新的 HTTP 客户端构建器,使用 [`crate::reqwest::SyncClient`] 作为 [`HttpCaller`] 实现
381    #[inline]
382    #[cfg(all(feature = "reqwest", feature = "async"))]
383    pub fn reqwest_async() -> Self {
384        Self::_new(Some(Box::<qiniu_reqwest::AsyncClient>::default()))
385    }
386
387    /// 创建一个新的 HTTP 客户端构建器,需要指定 [`HttpCaller`] 实现
388    #[inline]
389    pub fn new(http_caller: impl HttpCaller + 'static) -> Self {
390        Self::_new(Some(Box::new(http_caller)))
391    }
392
393    fn _new(http_caller: Option<Box<dyn HttpCaller>>) -> Self {
394        HttpClientBuilder {
395            http_caller,
396            use_https: true,
397            appended_user_agent: Default::default(),
398            request_retrier: Default::default(),
399            backoff: Default::default(),
400            chooser: Default::default(),
401            resolver: Default::default(),
402            callbacks: Default::default(),
403        }
404    }
405
406    /// 设置是否使用 HTTPS
407    ///
408    /// 默认为使用 HTTPS
409    #[inline]
410    pub fn use_https(&mut self, use_https: bool) -> &mut Self {
411        self.use_https = use_https;
412        self
413    }
414
415    /// 设置追加的 UserAgent
416    #[inline]
417    pub fn appended_user_agent(&mut self, appended_user_agent: impl Into<UserAgent>) -> &mut Self {
418        self.appended_user_agent = appended_user_agent.into();
419        self
420    }
421
422    /// 设置 HTTP 客户端实现
423    ///
424    /// 默认根据启用的功能自动选择。
425    #[inline]
426    pub fn http_caller(&mut self, http_caller: impl HttpCaller + 'static) -> &mut Self {
427        self.http_caller = Some(Box::new(http_caller));
428        self
429    }
430
431    /// 设置重试器
432    ///
433    /// 默认使用 [`ErrorRetrier`],并使用 [`LimitedRetrier`] 对其进行包装。
434    #[inline]
435    pub fn request_retrier(&mut self, request_retrier: impl RequestRetrier + 'static) -> &mut Self {
436        self.request_retrier = Some(Box::new(request_retrier));
437        self
438    }
439
440    /// 设置退避器
441    ///
442    /// 默认使用 [`ExponentialBackoff`],并使用 [`LimitedBackoff`] 和 [`RandomizedBackoff`] 对其进行包装。
443    #[inline]
444    pub fn backoff(&mut self, backoff: impl Backoff + 'static) -> &mut Self {
445        self.backoff = Some(Box::new(backoff));
446        self
447    }
448
449    /// 设置选择器
450    ///
451    /// 默认使用 [`SubnetChooser`],并使用 [`ShuffledChooser`] 和 [`NeverEmptyHandedChooser`] 对其进行包装。
452    #[inline]
453    pub fn chooser(&mut self, chooser: impl Chooser + 'static) -> &mut Self {
454        self.chooser = Some(Box::new(chooser));
455        self
456    }
457
458    /// 设置域名解析器
459    ///
460    /// 默认通过当前启用的功能来判定,并使用 [`CachedResolver`] 和 [`ShuffledResolver`] 对其进行包装。
461    #[inline]
462    pub fn resolver(&mut self, resolver: impl Resolver + 'static) -> &mut Self {
463        self.resolver = Some(Box::new(resolver));
464        self
465    }
466
467    /// 设置上传进度回调函数
468    #[inline]
469    pub fn on_uploading_progress(
470        &mut self,
471        callback: impl Fn(&dyn SimplifiedCallbackContext, TransferProgressInfo<'_>) -> AnyResult<()> + Send + Sync + 'static,
472    ) -> &mut Self {
473        self.callbacks.on_uploading_progress(callback);
474        self
475    }
476
477    /// 设置响应状态码回调函数
478    #[inline]
479    pub fn on_receive_response_status(
480        &mut self,
481        callback: impl Fn(&dyn SimplifiedCallbackContext, StatusCode) -> AnyResult<()> + Send + Sync + 'static,
482    ) -> &mut Self {
483        self.callbacks.on_receive_response_status(callback);
484        self
485    }
486
487    /// 设置响应 HTTP 头回调函数
488    #[inline]
489    pub fn on_receive_response_header(
490        &mut self,
491        callback: impl Fn(&dyn SimplifiedCallbackContext, &HeaderName, &HeaderValue) -> AnyResult<()>
492            + Send
493            + Sync
494            + 'static,
495    ) -> &mut Self {
496        self.callbacks.on_receive_response_header(callback);
497        self
498    }
499
500    /// 设置域名解析前回调函数
501    #[inline]
502    pub fn on_to_resolve_domain(
503        &mut self,
504        callback: impl Fn(&mut dyn CallbackContext, &str) -> AnyResult<()> + Send + Sync + 'static,
505    ) -> &mut Self {
506        self.callbacks.on_to_resolve_domain(callback);
507        self
508    }
509
510    /// 设置域名解析成功回调函数
511    #[inline]
512    pub fn on_domain_resolved(
513        &mut self,
514        callback: impl Fn(&mut dyn CallbackContext, &str, &ResolveAnswers) -> AnyResult<()> + Send + Sync + 'static,
515    ) -> &mut Self {
516        self.callbacks.on_domain_resolved(callback);
517        self
518    }
519
520    /// 设置 IP 地址选择前回调函数
521    #[inline]
522    pub fn on_to_choose_ips(
523        &mut self,
524        callback: impl Fn(&mut dyn CallbackContext, &[IpAddrWithPort]) -> AnyResult<()> + Send + Sync + 'static,
525    ) -> &mut Self {
526        self.callbacks.on_to_choose_ips(callback);
527        self
528    }
529
530    /// 设置 IP 地址选择成功回调函数
531    #[inline]
532    pub fn on_ips_chosen(
533        &mut self,
534        callback: impl Fn(&mut dyn CallbackContext, &[IpAddrWithPort], &[IpAddrWithPort]) -> AnyResult<()>
535            + Send
536            + Sync
537            + 'static,
538    ) -> &mut Self {
539        self.callbacks.on_ips_chosen(callback);
540        self
541    }
542
543    /// 设置 HTTP 请求签名前回调函数
544    #[inline]
545    pub fn on_before_request_signed(
546        &mut self,
547        callback: impl Fn(&mut dyn ExtendedCallbackContext) -> AnyResult<()> + Send + Sync + 'static,
548    ) -> &mut Self {
549        self.callbacks.on_before_request_signed(callback);
550        self
551    }
552
553    /// 设置 HTTP 请求前回调函数
554    #[inline]
555    pub fn on_after_request_signed(
556        &mut self,
557        callback: impl Fn(&mut dyn ExtendedCallbackContext) -> AnyResult<()> + Send + Sync + 'static,
558    ) -> &mut Self {
559        self.callbacks.on_after_request_signed(callback);
560        self
561    }
562
563    /// 设置 HTTP 响应成功回调函数
564    #[inline]
565    pub fn on_response(
566        &mut self,
567        callback: impl Fn(&mut dyn ExtendedCallbackContext, &ResponseParts) -> AnyResult<()> + Send + Sync + 'static,
568    ) -> &mut Self {
569        self.callbacks.on_response(callback);
570        self
571    }
572
573    /// 设置 HTTP 响应出错回调函数
574    #[inline]
575    pub fn on_error(
576        &mut self,
577        callback: impl Fn(&mut dyn ExtendedCallbackContext, &mut ResponseError) -> AnyResult<()> + Send + Sync + 'static,
578    ) -> &mut Self {
579        self.callbacks.on_error(callback);
580        self
581    }
582
583    /// 设置退避前回调函数
584    #[inline]
585    pub fn on_before_backoff(
586        &mut self,
587        callback: impl Fn(&mut dyn ExtendedCallbackContext, Duration) -> AnyResult<()> + Send + Sync + 'static,
588    ) -> &mut Self {
589        self.callbacks.on_before_backoff(callback);
590        self
591    }
592
593    /// 设置退避后回调函数
594    #[inline]
595    pub fn on_after_backoff(
596        &mut self,
597        callback: impl Fn(&mut dyn ExtendedCallbackContext, Duration) -> AnyResult<()> + Send + Sync + 'static,
598    ) -> &mut Self {
599        self.callbacks.on_after_backoff(callback);
600        self
601    }
602
603    /// 构建 HTTP 客户端
604    pub fn build(&mut self) -> HttpClient {
605        HttpClient {
606            inner: Arc::new(HttpClientInner {
607                use_https: replace(&mut self.use_https, true),
608                appended_user_agent: take(&mut self.appended_user_agent),
609                http_caller: take(&mut self.http_caller).unwrap_or_else(HttpClient::default_http_caller),
610                request_retrier: take(&mut self.request_retrier).unwrap_or_else(HttpClient::default_retrier),
611                backoff: take(&mut self.backoff).unwrap_or_else(HttpClient::default_backoff),
612                chooser: take(&mut self.chooser).unwrap_or_else(HttpClient::default_chooser),
613                resolver: take(&mut self.resolver).unwrap_or_else(HttpClient::default_resolver),
614                callbacks: self.callbacks.build(),
615            }),
616        }
617    }
618
619    #[allow(dead_code)]
620    fn assert() {
621        assert_impl!(Send: Self);
622        assert_impl!(Sync: Self);
623    }
624}
625
626impl Default for HttpClientBuilder {
627    #[inline]
628    fn default() -> Self {
629        HttpClientBuilder::_new(None)
630    }
631}
632
633impl Default for HttpClient {
634    #[inline]
635    fn default() -> Self {
636        HttpClientBuilder::default().build()
637    }
638}
639
640impl HttpClient {
641    /// 获得默认的 [`HttpCaller`] 实例
642    ///
643    /// 默认通过当前启用的功能来判定
644    #[inline]
645    pub fn default_http_caller() -> Box<dyn HttpCaller> {
646        cfg_if! {
647            if #[cfg(all(feature = "ureq", not(feature = "async")))] {
648                Box::new(qiniu_ureq::Client::default())
649            } else if #[cfg(feature = "isahc")] {
650                Box::new(qiniu_isahc::Client::default_client().expect("Failed to initialize isahc"))
651            } else if #[cfg(all(feature = "reqwest", not(feature = "async")))] {
652                Box::new(qiniu_reqwest::SyncClient::default())
653            } else if #[cfg(all(feature = "reqwest", feature = "async"))] {
654                Box::new(qiniu_reqwest::AsyncClient::default())
655            } else {
656                panic!("No http caller available, can you enable feature `isahc` to resolve this problem?")
657            }
658        }
659    }
660
661    /// 获得默认的 [`Resolver`] 实例
662    ///
663    /// 默认通过当前启用的功能来判定,并使用 [`CachedResolver`] 和 [`ShuffledResolver`] 对其进行包装。
664    pub fn default_resolver() -> Box<dyn Resolver> {
665        let chained_resolver = {
666            let base_resolver = Box::<TimeoutResolver<SimpleResolver>>::default();
667
668            #[allow(unused_mut)]
669            let mut builder = ChainedResolver::builder(base_resolver);
670
671            #[cfg(feature = "c_ares")]
672            if let Ok(resolver) = super::CAresResolver::new() {
673                builder.prepend_resolver(Box::new(resolver));
674            }
675
676            #[cfg(all(feature = "trust_dns", feature = "async"))]
677            if let Ok(resolver) = async_std::task::block_on(async { super::TrustDnsResolver::from_system_conf().await })
678            {
679                builder.prepend_resolver(Box::new(resolver));
680            }
681
682            builder.build()
683        };
684        let cached_resolver = CachedResolver::builder(chained_resolver).in_memory();
685        let shuffled_resolver = ShuffledResolver::new(cached_resolver);
686        Box::new(shuffled_resolver)
687    }
688
689    /// 获得默认的 [`Chooser`] 实例
690    ///
691    /// 默认使用 [`SubnetChooser`],并使用 [`ShuffledChooser`] 和 [`NeverEmptyHandedChooser`] 对其进行包装。
692    #[inline]
693    pub fn default_chooser() -> Box<dyn Chooser> {
694        Box::<NeverEmptyHandedChooser<ShuffledChooser<SubnetChooser>>>::default()
695    }
696
697    /// 获得默认的 [`RequestRetrier`] 实例
698    ///
699    /// 默认使用 [`ErrorRetrier`],并使用 [`LimitedRetrier`] 对其进行包装。
700    #[inline]
701    pub fn default_retrier() -> Box<dyn RequestRetrier> {
702        Box::<LimitedRetrier<ErrorRetrier>>::default()
703    }
704
705    /// 获得默认的 [`Backoff`] 实例
706    ///
707    /// 默认使用 [`ExponentialBackoff`],并使用 [`LimitedBackoff`] 和 [`RandomizedBackoff`] 对其进行包装。
708    #[inline]
709    pub fn default_backoff() -> Box<dyn Backoff> {
710        Box::<LimitedBackoff<RandomizedBackoff<ExponentialBackoff>>>::default()
711    }
712}