qiniu_http_client/client/request/
builder.rs

1use super::{
2    super::{
3        super::{EndpointsProvider, IpAddrWithPort, ServiceName},
4        callbacks::CallbacksBuilder,
5        request_call, ApiResult, Authorization, CallbackContext, ExtendedCallbackContext, HttpClient, ResolveAnswers,
6        ResponseError, SimplifiedCallbackContext, SyncResponse,
7    },
8    multipart::SyncMultipart,
9    request_metadata::RequestMetadata,
10    Idempotent, QueryPair, QueryPairKey, QueryPairValue, SyncInnerRequest,
11};
12use anyhow::Result as AnyResult;
13use assert_impl::assert_impl;
14use mime::{Mime, APPLICATION_JSON, APPLICATION_OCTET_STREAM, APPLICATION_WWW_FORM_URLENCODED};
15use qiniu_http::{
16    header::{IntoHeaderName, ACCEPT, CONTENT_TYPE},
17    Extensions, HeaderMap, HeaderName, HeaderValue, Method, Reset, ResponseParts, StatusCode, SyncRequestBody,
18    TransferProgressInfo, UserAgent, Version,
19};
20use serde::Serialize;
21use serde_json::Result as JsonResult;
22use std::{
23    borrow::{Borrow, Cow},
24    fmt::Debug,
25    io::{Read, Result as IoResult},
26    mem::take,
27    time::Duration,
28};
29
30#[cfg(feature = "async")]
31use {
32    super::{
33        super::{async_request_call, AsyncResponse},
34        multipart::AsyncMultipart,
35        AsyncInnerRequest,
36    },
37    futures::io::AsyncRead,
38    qiniu_http::{AsyncRequestBody, AsyncReset},
39};
40
41/// HTTP 请求构建器部分参数
42///
43/// 包含 HTTP 请求构建器内除请求体和终端地址提供者以外的参数
44#[derive(Default, Debug)]
45pub struct RequestBuilderParts<'r> {
46    callbacks: CallbacksBuilder<'r>,
47    metadata: RequestMetadata<'r>,
48    extensions: Extensions,
49    appended_user_agent: UserAgent,
50}
51
52impl<'r> RequestBuilderParts<'r> {
53    /// 设置是否使用 HTTPS
54    #[inline]
55    pub fn use_https(&mut self, use_https: bool) -> &mut Self {
56        self.metadata.use_https = Some(use_https);
57        self
58    }
59
60    /// 设置 HTTP 协议版本
61    #[inline]
62    pub fn version(&mut self, version: Version) -> &mut Self {
63        self.metadata.version = version;
64        self
65    }
66
67    /// 设置 HTTP 请求路径
68    #[inline]
69    pub fn path(&mut self, path: impl Into<Cow<'r, str>>) -> &mut Self {
70        self.metadata.path = path.into();
71        self
72    }
73
74    /// 设置 HTTP 请求头
75    #[inline]
76    pub fn headers(&mut self, headers: impl Into<Cow<'r, HeaderMap>>) -> &mut Self {
77        self.metadata.headers = headers.into();
78        self
79    }
80
81    /// 添加 HTTP 请求头
82    #[inline]
83    pub fn set_header(&mut self, header_name: impl IntoHeaderName, header_value: impl Into<HeaderValue>) -> &mut Self {
84        self.metadata.headers.to_mut().insert(header_name, header_value.into());
85        self
86    }
87
88    fn set_content_type(&mut self, content_type: Option<Mime>) -> &mut Self {
89        self.set_header(
90            CONTENT_TYPE,
91            HeaderValue::from_str(content_type.as_ref().unwrap_or(&APPLICATION_OCTET_STREAM).as_ref()).unwrap(),
92        )
93    }
94
95    /// 设置 HTTP 响应预期为 JSON 类型
96    #[inline]
97    pub fn accept_json(&mut self) -> &mut Self {
98        self.set_accept(APPLICATION_JSON)
99    }
100
101    /// 设置 HTTP 响应预期为二进制流类型
102    #[inline]
103    pub fn accept_application_octet_stream(&mut self) -> &mut Self {
104        self.set_accept(APPLICATION_OCTET_STREAM)
105    }
106
107    fn set_accept(&mut self, accept: Mime) -> &mut Self {
108        self.set_header(ACCEPT, HeaderValue::from_str(accept.as_ref()).unwrap())
109    }
110
111    /// 设置查询参数
112    #[inline]
113    pub fn query(&mut self, query: impl Into<Cow<'r, str>>) -> &mut Self {
114        self.metadata.query = query.into();
115        self
116    }
117
118    /// 设置查询参数
119    #[inline]
120    pub fn query_pairs(&mut self, query_pairs: impl Into<Vec<QueryPair<'r>>>) -> &mut Self {
121        self.metadata.query_pairs = query_pairs.into();
122        self
123    }
124
125    /// 追加查询参数
126    #[inline]
127    pub fn append_query_pair(
128        &mut self,
129        query_pair_key: impl Into<QueryPairKey<'r>>,
130        query_pair_value: impl Into<QueryPairValue<'r>>,
131    ) -> &mut Self {
132        self.metadata
133            .query_pairs
134            .push((query_pair_key.into(), query_pair_value.into()));
135        self
136    }
137
138    /// 追加 UserAgent
139    #[inline]
140    pub fn appended_user_agent(&mut self, user_agent: impl Into<UserAgent>) -> &mut Self {
141        self.appended_user_agent = user_agent.into();
142        self
143    }
144
145    /// 设置鉴权签名
146    #[inline]
147    pub fn authorization(&mut self, authorization: Authorization<'r>) -> &mut Self {
148        self.metadata.authorization = Some(authorization);
149        self
150    }
151
152    /// 设置为幂等请求
153    #[inline]
154    pub fn idempotent(&mut self, idempotent: Idempotent) -> &mut Self {
155        self.metadata.idempotent = idempotent;
156        self
157    }
158
159    /// 设置扩展信息
160    #[inline]
161    pub fn extensions(&mut self, extensions: Extensions) -> &mut Self {
162        self.extensions = extensions;
163        self
164    }
165
166    /// 添加扩展信息
167    #[inline]
168    pub fn add_extension<T: Send + Sync + 'static>(&mut self, val: T) -> &mut Self {
169        self.extensions.insert(val);
170        self
171    }
172
173    /// 设置上传进度回调函数
174    #[inline]
175    pub fn on_uploading_progress(
176        &mut self,
177        callback: impl Fn(&dyn SimplifiedCallbackContext, TransferProgressInfo<'_>) -> AnyResult<()> + Send + Sync + 'r,
178    ) -> &mut Self {
179        self.callbacks.on_uploading_progress(callback);
180        self
181    }
182
183    /// 设置响应状态码回调函数
184    #[inline]
185
186    pub fn on_receive_response_status(
187        &mut self,
188        callback: impl Fn(&dyn SimplifiedCallbackContext, StatusCode) -> AnyResult<()> + Send + Sync + 'r,
189    ) -> &mut Self {
190        self.callbacks.on_receive_response_status(callback);
191        self
192    }
193
194    /// 设置响应 HTTP 头回调函数
195    #[inline]
196    pub fn on_receive_response_header(
197        &mut self,
198        callback: impl Fn(&dyn SimplifiedCallbackContext, &HeaderName, &HeaderValue) -> AnyResult<()> + Send + Sync + 'r,
199    ) -> &mut Self {
200        self.callbacks.on_receive_response_header(callback);
201        self
202    }
203
204    /// 设置域名解析前回调函数
205    #[inline]
206    pub fn on_to_resolve_domain(
207        &mut self,
208        callback: impl Fn(&mut dyn CallbackContext, &str) -> AnyResult<()> + Send + Sync + 'r,
209    ) -> &mut Self {
210        self.callbacks.on_to_resolve_domain(callback);
211        self
212    }
213
214    /// 设置域名解析成功回调函数
215    #[inline]
216    pub fn on_domain_resolved(
217        &mut self,
218        callback: impl Fn(&mut dyn CallbackContext, &str, &ResolveAnswers) -> AnyResult<()> + Send + Sync + 'r,
219    ) -> &mut Self {
220        self.callbacks.on_domain_resolved(callback);
221        self
222    }
223
224    /// 设置 IP 地址选择前回调函数
225    #[inline]
226    pub fn on_to_choose_ips(
227        &mut self,
228        callback: impl Fn(&mut dyn CallbackContext, &[IpAddrWithPort]) -> AnyResult<()> + Send + Sync + 'r,
229    ) -> &mut Self {
230        self.callbacks.on_to_choose_ips(callback);
231        self
232    }
233
234    /// 设置 IP 地址选择成功回调函数
235    #[inline]
236    pub fn on_ips_chosen(
237        &mut self,
238        callback: impl Fn(&mut dyn CallbackContext, &[IpAddrWithPort], &[IpAddrWithPort]) -> AnyResult<()>
239            + Send
240            + Sync
241            + 'r,
242    ) -> &mut Self {
243        self.callbacks.on_ips_chosen(callback);
244        self
245    }
246
247    /// 设置 HTTP 请求签名前回调函数
248    #[inline]
249    pub fn on_before_request_signed(
250        &mut self,
251        callback: impl Fn(&mut dyn ExtendedCallbackContext) -> AnyResult<()> + Send + Sync + 'r,
252    ) -> &mut Self {
253        self.callbacks.on_before_request_signed(callback);
254        self
255    }
256
257    /// 设置 HTTP 请求前回调函数
258    #[inline]
259    pub fn on_after_request_signed(
260        &mut self,
261        callback: impl Fn(&mut dyn ExtendedCallbackContext) -> AnyResult<()> + Send + Sync + 'r,
262    ) -> &mut Self {
263        self.callbacks.on_after_request_signed(callback);
264        self
265    }
266
267    /// 设置响应成功回调函数
268    #[inline]
269    pub fn on_response(
270        &mut self,
271        callback: impl Fn(&mut dyn ExtendedCallbackContext, &ResponseParts) -> AnyResult<()> + Send + Sync + 'r,
272    ) -> &mut Self {
273        self.callbacks.on_response(callback);
274        self
275    }
276
277    /// 设置响应错误回调函数
278    #[inline]
279    pub fn on_error(
280        &mut self,
281        callback: impl Fn(&mut dyn ExtendedCallbackContext, &mut ResponseError) -> AnyResult<()> + Send + Sync + 'r,
282    ) -> &mut Self {
283        self.callbacks.on_error(callback);
284        self
285    }
286
287    /// 设置退避前回调函数
288    #[inline]
289    pub fn on_before_backoff(
290        &mut self,
291        callback: impl Fn(&mut dyn ExtendedCallbackContext, Duration) -> AnyResult<()> + Send + Sync + 'r,
292    ) -> &mut Self {
293        self.callbacks.on_before_backoff(callback);
294        self
295    }
296
297    /// 设置退避后回调函数
298    #[inline]
299    pub fn on_after_backoff(
300        &mut self,
301        callback: impl Fn(&mut dyn ExtendedCallbackContext, Duration) -> AnyResult<()> + Send + Sync + 'r,
302    ) -> &mut Self {
303        self.callbacks.on_after_backoff(callback);
304        self
305    }
306
307    /// 构建为请求部分参数
308    #[inline]
309    pub fn build(self) -> RequestParts<'r> {
310        RequestParts {
311            metadata: self.metadata,
312            extensions: self.extensions,
313            appended_user_agent: self.appended_user_agent,
314        }
315    }
316
317    #[allow(dead_code)]
318    fn ignore() {
319        assert_impl!(Send: Self);
320        assert_impl!(Sync: Self);
321    }
322}
323
324/// 请求构建器
325///
326/// 通过 [`HttpClient::get`], [`HttpClient::post`] 等方法创建请求构建器
327#[derive(Debug)]
328pub struct RequestBuilder<'r, B: 'r, E: 'r> {
329    http_client: &'r HttpClient,
330    service_names: &'r [ServiceName],
331    endpoints_provider: E,
332    parts: RequestBuilderParts<'r>,
333    body: B,
334}
335
336impl<'r, B: Default + 'r, E: EndpointsProvider + 'r> RequestBuilder<'r, B, E> {
337    pub(in super::super) fn new(
338        http_client: &'r HttpClient,
339        method: Method,
340        endpoints_provider: E,
341        service_names: &'r [ServiceName],
342    ) -> Self {
343        Self {
344            http_client,
345            service_names,
346            endpoints_provider,
347            parts: RequestBuilderParts {
348                metadata: RequestMetadata {
349                    method,
350                    ..Default::default()
351                },
352                ..Default::default()
353            },
354            body: Default::default(),
355        }
356    }
357}
358
359impl<'r, B: 'r, E: 'r> RequestBuilder<'r, B, E> {
360    /// 设置是否使用 HTTPS
361    #[inline]
362    pub fn use_https(&mut self, use_https: bool) -> &mut Self {
363        self.parts.use_https(use_https);
364        self
365    }
366
367    /// 设置 HTTP 协议版本
368    #[inline]
369    pub fn version(&mut self, version: Version) -> &mut Self {
370        self.parts.version(version);
371        self
372    }
373
374    /// 设置 HTTP 请求路径
375    #[inline]
376    pub fn path(&mut self, path: impl Into<Cow<'r, str>>) -> &mut Self {
377        self.parts.path(path);
378        self
379    }
380
381    /// 设置 HTTP 请求头
382    #[inline]
383    pub fn headers(&mut self, headers: impl Into<Cow<'r, HeaderMap>>) -> &mut Self {
384        self.parts.headers(headers);
385        self
386    }
387
388    /// 添加 HTTP 请求头
389    #[inline]
390    pub fn set_header(&mut self, header_name: impl IntoHeaderName, header_value: impl Into<HeaderValue>) -> &mut Self {
391        self.parts.set_header(header_name, header_value);
392        self
393    }
394
395    /// 设置 HTTP 响应预期为 JSON 类型
396    #[inline]
397    pub fn accept_json(&mut self) -> &mut Self {
398        self.parts.accept_json();
399        self
400    }
401
402    /// 设置 HTTP 响应预期为二进制流类型
403    #[inline]
404    pub fn accept_application_octet_stream(&mut self) -> &mut Self {
405        self.parts.accept_application_octet_stream();
406        self
407    }
408
409    /// 设置查询参数
410    #[inline]
411    pub fn query(&mut self, query: impl Into<Cow<'r, str>>) -> &mut Self {
412        self.parts.query(query);
413        self
414    }
415
416    /// 设置查询参数
417    #[inline]
418    pub fn query_pairs(&mut self, query_pairs: impl Into<Vec<QueryPair<'r>>>) -> &mut Self {
419        self.parts.query_pairs(query_pairs);
420        self
421    }
422
423    /// 追加查询参数
424    #[inline]
425    pub fn append_query_pair(
426        &mut self,
427        query_pair_key: impl Into<QueryPairKey<'r>>,
428        query_pair_value: impl Into<QueryPairValue<'r>>,
429    ) -> &mut Self {
430        self.parts.append_query_pair(query_pair_key, query_pair_value);
431        self
432    }
433
434    /// 追加 UserAgent
435    #[inline]
436    pub fn appended_user_agent(&mut self, user_agent: impl Into<UserAgent>) -> &mut Self {
437        self.parts.appended_user_agent(user_agent);
438        self
439    }
440
441    /// 设置鉴权签名
442    #[inline]
443    pub fn authorization(&mut self, authorization: Authorization<'r>) -> &mut Self {
444        self.parts.authorization(authorization);
445        self
446    }
447
448    /// 设置为幂等请求
449    #[inline]
450    pub fn idempotent(&mut self, idempotent: Idempotent) -> &mut Self {
451        self.parts.idempotent(idempotent);
452        self
453    }
454
455    /// 设置扩展信息
456    #[inline]
457    pub fn extensions(&mut self, extensions: Extensions) -> &mut Self {
458        self.parts.extensions(extensions);
459        self
460    }
461
462    /// 添加扩展信息
463    #[inline]
464    pub fn add_extension<T: Send + Sync + 'static>(&mut self, val: T) -> &mut Self {
465        self.parts.add_extension(val);
466        self
467    }
468
469    /// 设置上传进度回调函数
470    #[inline]
471    pub fn on_uploading_progress(
472        &mut self,
473        callback: impl Fn(&dyn SimplifiedCallbackContext, TransferProgressInfo<'_>) -> AnyResult<()> + Send + Sync + 'r,
474    ) -> &mut Self {
475        self.parts.on_uploading_progress(callback);
476        self
477    }
478
479    /// 设置响应状态码回调函数
480    #[inline]
481    pub fn on_receive_response_status(
482        &mut self,
483        callback: impl Fn(&dyn SimplifiedCallbackContext, StatusCode) -> AnyResult<()> + Send + Sync + 'r,
484    ) -> &mut Self {
485        self.parts.on_receive_response_status(callback);
486        self
487    }
488
489    /// 设置响应 HTTP 头回调函数
490    #[inline]
491    pub fn on_receive_response_header(
492        &mut self,
493        callback: impl Fn(&dyn SimplifiedCallbackContext, &HeaderName, &HeaderValue) -> AnyResult<()> + Send + Sync + 'r,
494    ) -> &mut Self {
495        self.parts.on_receive_response_header(callback);
496        self
497    }
498
499    /// 设置域名解析前回调函数
500    #[inline]
501    pub fn on_to_resolve_domain(
502        &mut self,
503        callback: impl Fn(&mut dyn CallbackContext, &str) -> AnyResult<()> + Send + Sync + 'r,
504    ) -> &mut Self {
505        self.parts.on_to_resolve_domain(callback);
506        self
507    }
508
509    /// 设置域名解析成功回调函数
510    #[inline]
511    pub fn on_domain_resolved(
512        &mut self,
513        callback: impl Fn(&mut dyn CallbackContext, &str, &ResolveAnswers) -> AnyResult<()> + Send + Sync + 'r,
514    ) -> &mut Self {
515        self.parts.on_domain_resolved(callback);
516        self
517    }
518
519    /// 设置 IP 地址选择前回调函数
520    #[inline]
521    pub fn on_to_choose_ips(
522        &mut self,
523        callback: impl Fn(&mut dyn CallbackContext, &[IpAddrWithPort]) -> AnyResult<()> + Send + Sync + 'r,
524    ) -> &mut Self {
525        self.parts.on_to_choose_ips(callback);
526        self
527    }
528
529    /// 设置 IP 地址选择成功回调函数
530    #[inline]
531    pub fn on_ips_chosen(
532        &mut self,
533        callback: impl Fn(&mut dyn CallbackContext, &[IpAddrWithPort], &[IpAddrWithPort]) -> AnyResult<()>
534            + Send
535            + Sync
536            + 'r,
537    ) -> &mut Self {
538        self.parts.on_ips_chosen(callback);
539        self
540    }
541
542    /// 设置 HTTP 请求签名前回调函数
543    #[inline]
544    pub fn on_before_request_signed(
545        &mut self,
546        callback: impl Fn(&mut dyn ExtendedCallbackContext) -> AnyResult<()> + Send + Sync + 'r,
547    ) -> &mut Self {
548        self.parts.on_before_request_signed(callback);
549        self
550    }
551
552    /// 设置 HTTP 请求前回调函数
553    #[inline]
554    pub fn on_after_request_signed(
555        &mut self,
556        callback: impl Fn(&mut dyn ExtendedCallbackContext) -> AnyResult<()> + Send + Sync + 'r,
557    ) -> &mut Self {
558        self.parts.on_after_request_signed(callback);
559        self
560    }
561
562    /// 设置响应成功回调函数
563    #[inline]
564    pub fn on_response(
565        &mut self,
566        callback: impl Fn(&mut dyn ExtendedCallbackContext, &ResponseParts) -> AnyResult<()> + Send + Sync + 'r,
567    ) -> &mut Self {
568        self.parts.on_response(callback);
569        self
570    }
571
572    /// 设置响应错误回调函数
573    #[inline]
574    pub fn on_error(
575        &mut self,
576        callback: impl Fn(&mut dyn ExtendedCallbackContext, &mut ResponseError) -> AnyResult<()> + Send + Sync + 'r,
577    ) -> &mut Self {
578        self.parts.on_error(callback);
579        self
580    }
581
582    /// 设置退避前回调函数
583    #[inline]
584    pub fn on_before_backoff(
585        &mut self,
586        callback: impl Fn(&mut dyn ExtendedCallbackContext, Duration) -> AnyResult<()> + Send + Sync + 'r,
587    ) -> &mut Self {
588        self.parts.on_before_backoff(callback);
589        self
590    }
591
592    /// 设置退避后回调函数
593    #[inline]
594    pub fn on_after_backoff(
595        &mut self,
596        callback: impl Fn(&mut dyn ExtendedCallbackContext, Duration) -> AnyResult<()> + Send + Sync + 'r,
597    ) -> &mut Self {
598        self.parts.on_after_backoff(callback);
599        self
600    }
601
602    /// 获取 HTTP 请求构建器部分参数
603    #[inline]
604    pub fn parts(&self) -> &RequestBuilderParts<'r> {
605        &self.parts
606    }
607
608    /// 获取 HTTP 请求构建器部分参数的可变引用
609    #[inline]
610    pub fn parts_mut(&mut self) -> &mut RequestBuilderParts<'r> {
611        &mut self.parts
612    }
613
614    /// 转换为 HTTP 请求构建器部分参数
615    #[inline]
616    pub fn into_parts(self) -> RequestBuilderParts<'r> {
617        self.parts
618    }
619
620    fn get_appended_user_agent(&self) -> UserAgent {
621        let mut appended_user_agent = self.http_client.appended_user_agent().to_owned();
622        appended_user_agent.push_str(self.parts.appended_user_agent.as_str());
623        appended_user_agent
624    }
625}
626
627impl<'r, B: Sync + Send + 'r, E: Sync + Send + 'r> RequestBuilder<'r, B, E> {
628    #[allow(dead_code)]
629    fn ignore() {
630        assert_impl!(Send: Self);
631        assert_impl!(Sync: Self);
632    }
633}
634
635/// 阻塞请求构建器
636pub type SyncRequestBuilder<'r, E> = RequestBuilder<'r, SyncRequestBody<'r>, E>;
637
638impl<'r, E: 'r> SyncRequestBuilder<'r, E> {
639    /// 设置 HTTP 请求体为输入流
640    #[inline]
641    pub fn stream_as_body(
642        &mut self,
643        body: impl Read + Reset + Debug + Send + Sync + 'static,
644        content_length: u64,
645        content_type: Option<Mime>,
646    ) -> &mut Self {
647        self.body = SyncRequestBody::from_reader(body, content_length);
648        self.parts.set_content_type(content_type);
649        self
650    }
651
652    /// 设置 HTTP 请求体为输入流的可变引用
653    #[inline]
654    pub fn referenced_stream_as_body<T: Read + Reset + Debug + Send + Sync>(
655        &mut self,
656        body: &'r mut T,
657        content_length: u64,
658        content_type: Option<Mime>,
659    ) -> &mut Self {
660        self.body = SyncRequestBody::from_referenced_reader(body, content_length);
661        self.parts.set_content_type(content_type);
662        self
663    }
664
665    /// 设置 HTTP 请求体为内存数据
666    #[inline]
667    pub fn bytes_as_body(&mut self, body: impl Into<Vec<u8>>, content_type: Option<Mime>) -> &mut Self {
668        self.body = SyncRequestBody::from_bytes(body.into());
669        self.parts.set_content_type(content_type);
670        self
671    }
672
673    /// 设置 HTTP 请求体为内存数据的引用
674    #[inline]
675    pub fn referenced_bytes_as_body(&mut self, body: &'r [u8], content_type: Option<Mime>) -> &mut Self {
676        self.body = SyncRequestBody::from_referenced_bytes(body);
677        self.parts.set_content_type(content_type);
678        self
679    }
680
681    /// 设置 HTTP 请求体为 JSON 对象
682    #[inline]
683    pub fn json(&mut self, body: impl Serialize) -> JsonResult<&mut Self> {
684        Ok(self.bytes_as_body(serde_json::to_vec(&body)?, Some(APPLICATION_JSON)))
685    }
686
687    /// 设置 HTTP 请求体为表单对象
688    #[inline]
689    pub fn post_form<I, K, V>(&mut self, iter: I) -> &mut Self
690    where
691        I: IntoIterator,
692        I::Item: Borrow<(K, Option<V>)>,
693        K: AsRef<str>,
694        V: AsRef<str>,
695    {
696        let mut form = form_urlencoded::Serializer::new(String::new());
697        for pair in iter {
698            let (k, v) = pair.borrow();
699            if let Some(v) = v {
700                form.append_pair(k.as_ref(), v.as_ref());
701            } else {
702                form.append_key_only(k.as_ref());
703            }
704        }
705        self.bytes_as_body(form.finish().into_bytes(), Some(APPLICATION_WWW_FORM_URLENCODED))
706    }
707
708    /// 设置 HTTP 请求体为 Multipart 表单对象
709    #[inline]
710    pub fn multipart<'a>(&mut self, multipart: impl Into<SyncMultipart<'a>>) -> IoResult<&mut Self> {
711        let mut buf = Vec::new();
712        let multipart = multipart.into();
713        let mime = ("multipart/form-data; boundary=".to_owned() + multipart.boundary())
714            .parse()
715            .unwrap();
716        multipart.into_read().read_to_end(&mut buf)?;
717        Ok(self.bytes_as_body(buf, Some(mime)))
718    }
719}
720
721impl<'r, E: EndpointsProvider + Clone + 'r> SyncRequestBuilder<'r, E> {
722    /// 阻塞发起 HTTP 请求
723    #[inline]
724    pub fn call(&mut self) -> ApiResult<SyncResponse> {
725        request_call(self.build())
726    }
727
728    pub(in super::super) fn build(&mut self) -> SyncInnerRequest<'r, E> {
729        SyncInnerRequest::new(
730            self.http_client,
731            self.endpoints_provider.to_owned(),
732            self.service_names,
733            self.parts.callbacks.build(),
734            take(&mut self.parts.metadata),
735            take(&mut self.body),
736            self.get_appended_user_agent(),
737            take(&mut self.parts.extensions),
738        )
739    }
740}
741
742/// 异步请求构建器
743#[cfg(feature = "async")]
744pub type AsyncRequestBuilder<'r, E> = RequestBuilder<'r, AsyncRequestBody<'r>, E>;
745
746#[cfg(feature = "async")]
747impl<'r, E: 'r> AsyncRequestBuilder<'r, E> {
748    /// 设置 HTTP 请求体为异步输入流
749    #[inline]
750    pub fn stream_as_body(
751        &mut self,
752        body: impl AsyncRead + AsyncReset + Unpin + Debug + Send + Sync + 'static,
753        content_length: u64,
754        content_type: Option<Mime>,
755    ) -> &mut Self {
756        self.body = AsyncRequestBody::from_reader(body, content_length);
757        self.parts.set_content_type(content_type);
758        self
759    }
760
761    /// 设置 HTTP 请求体为异步输入流的可变引用
762    #[inline]
763    pub fn referenced_stream_as_body<T: AsyncRead + AsyncReset + Unpin + Debug + Send + Sync>(
764        &mut self,
765        body: &'r mut T,
766        content_length: u64,
767        content_type: Option<Mime>,
768    ) -> &mut Self {
769        self.body = AsyncRequestBody::from_referenced_reader(body, content_length);
770        self.parts.set_content_type(content_type);
771        self
772    }
773
774    /// 设置 HTTP 请求体为内存数据
775    #[inline]
776    pub fn bytes_as_body(&mut self, body: impl Into<Vec<u8>>, content_type: Option<Mime>) -> &mut Self {
777        self.body = AsyncRequestBody::from_bytes(body.into());
778        self.parts.set_content_type(content_type);
779        self
780    }
781
782    /// 设置 HTTP 请求体为内存数据的引用
783    #[inline]
784    pub fn referenced_bytes_as_body(&mut self, body: &'r [u8], content_type: Option<Mime>) -> &mut Self {
785        self.body = AsyncRequestBody::from_referenced_bytes(body);
786        self.parts.set_content_type(content_type);
787        self
788    }
789
790    /// 设置 HTTP 请求体为 JSON 对象
791    #[inline]
792    pub fn json(&mut self, body: impl Serialize) -> JsonResult<&mut Self> {
793        Ok(self.bytes_as_body(serde_json::to_vec(&body)?, Some(APPLICATION_JSON)))
794    }
795
796    /// 设置 HTTP 请求体为表单对象
797    #[inline]
798    pub fn post_form<I, K, V>(&mut self, iter: I) -> &mut Self
799    where
800        I: IntoIterator,
801        I::Item: Borrow<(K, Option<V>)>,
802        K: AsRef<str>,
803        V: AsRef<str>,
804    {
805        let mut form = form_urlencoded::Serializer::new(String::new());
806        for pair in iter {
807            let (k, v) = pair.borrow();
808            if let Some(v) = v {
809                form.append_pair(k.as_ref(), v.as_ref());
810            } else {
811                form.append_key_only(k.as_ref());
812            }
813        }
814        self.bytes_as_body(form.finish().into_bytes(), Some(APPLICATION_WWW_FORM_URLENCODED))
815    }
816
817    /// 设置 HTTP 请求体为 Multipart 表单对象
818    #[inline]
819    pub async fn multipart<'a>(
820        &mut self,
821        multipart: impl Into<AsyncMultipart<'a>>,
822    ) -> IoResult<&mut RequestBuilder<'r, AsyncRequestBody<'r>, E>> {
823        use futures::AsyncReadExt;
824
825        let mut buf = Vec::new();
826        let multipart = multipart.into();
827        let mime = ("multipart/form-data; boundary=".to_owned() + multipart.boundary())
828            .parse()
829            .unwrap();
830        multipart.into_async_read().read_to_end(&mut buf).await?;
831        Ok(self.bytes_as_body(buf, Some(mime)))
832    }
833}
834
835#[cfg(feature = "async")]
836impl<'r, E: EndpointsProvider + Clone + 'r> AsyncRequestBuilder<'r, E> {
837    /// 异步发起 HTTP 请求
838    #[inline]
839    pub async fn call(&mut self) -> ApiResult<AsyncResponse> {
840        async_request_call(self.build()).await
841    }
842
843    pub(in super::super) fn build(&mut self) -> AsyncInnerRequest<'r, E> {
844        AsyncInnerRequest::new(
845            self.http_client,
846            self.endpoints_provider.to_owned(),
847            self.service_names,
848            self.parts.callbacks.build(),
849            take(&mut self.parts.metadata),
850            take(&mut self.body),
851            self.get_appended_user_agent(),
852            take(&mut self.parts.extensions),
853        )
854    }
855}
856
857/// HTTP 请求部分参数
858///
859/// 包含 HTTP 请求内除请求体和终端地址提供者以外的参数
860#[derive(Default, Debug)]
861pub struct RequestParts<'r> {
862    metadata: RequestMetadata<'r>,
863    extensions: Extensions,
864    appended_user_agent: UserAgent,
865}
866
867impl CallbackContext for RequestParts<'_> {
868    #[inline]
869    fn extensions(&self) -> &Extensions {
870        &self.extensions
871    }
872
873    #[inline]
874    fn extensions_mut(&mut self) -> &mut Extensions {
875        &mut self.extensions
876    }
877}
878
879impl SimplifiedCallbackContext for RequestParts<'_> {
880    #[inline]
881    fn use_https(&self) -> bool {
882        self.metadata.use_https.unwrap_or(true)
883    }
884
885    #[inline]
886    fn method(&self) -> &Method {
887        &self.metadata.method
888    }
889
890    #[inline]
891    fn version(&self) -> Version {
892        self.metadata.version
893    }
894
895    #[inline]
896    fn path(&self) -> &str {
897        &self.metadata.path
898    }
899
900    #[inline]
901    fn query(&self) -> &str {
902        &self.metadata.query
903    }
904
905    #[inline]
906    fn query_pairs(&self) -> &[QueryPair] {
907        &self.metadata.query_pairs
908    }
909
910    #[inline]
911    fn headers(&self) -> &HeaderMap {
912        &self.metadata.headers
913    }
914
915    #[inline]
916    fn appended_user_agent(&self) -> &UserAgent {
917        &self.appended_user_agent
918    }
919
920    #[inline]
921    fn authorization(&self) -> Option<&Authorization> {
922        self.metadata.authorization.as_ref()
923    }
924
925    #[inline]
926    fn idempotent(&self) -> Idempotent {
927        self.metadata.idempotent
928    }
929}
930
931impl RequestParts<'_> {
932    #[allow(dead_code)]
933    fn ignore() {
934        assert_impl!(Send: Self);
935        assert_impl!(Sync: Self);
936    }
937}