qiniu_http/
lib.rs

1#![cfg_attr(feature = "docs", feature(doc_cfg))]
2#![deny(
3    single_use_lifetimes,
4    missing_debug_implementations,
5    large_assignments,
6    exported_private_dependencies,
7    absolute_paths_not_starting_with_crate,
8    anonymous_parameters,
9    explicit_outlives_requirements,
10    keyword_idents,
11    macro_use_extern_crate,
12    meta_variable_misuse,
13    missing_docs,
14    non_ascii_idents,
15    indirect_structural_match,
16    trivial_casts,
17    trivial_numeric_casts,
18    unsafe_code,
19    unreachable_pub,
20    unused_crate_dependencies,
21    unused_extern_crates,
22    unused_import_braces,
23    unused_lifetimes,
24    unused_qualifications
25)]
26
27//! # qiniu-http
28//!
29//! ## 七牛 HTTP 客户端接口库
30//!
31//! 为更高层的 HTTP 客户端提供基础 HTTP 请求接口 [`HttpCaller`](同时提供阻塞接口和异步接口,异步接口则需要启用 `async` 功能),
32//! 使不同的 HTTP 客户端基于相同的接口实现,
33//! 以便于七牛 API 调用层可以灵活切换 HTTP 客户端实现。
34//! 该接口库只关注 HTTP 调用相关逻辑,不包含七牛 API 调用相关逻辑。
35
36mod callback;
37mod error;
38mod request;
39mod response;
40
41use auto_impl::auto_impl;
42pub use callback::{OnHeaderCallback, OnProgressCallback, OnStatusCodeCallback, TransferProgressInfo};
43pub use error::{
44    Error as ResponseError, ErrorBuilder as ResponseErrorBuilder, ErrorKind as ResponseErrorKind, MapError,
45};
46pub use http::{
47    header::{self, HeaderMap, HeaderName, HeaderValue, InvalidHeaderName, InvalidHeaderValue},
48    method::{InvalidMethod, Method},
49    status::{InvalidStatusCode, StatusCode},
50    uri::{self, Uri},
51    Extensions, Version,
52};
53use once_cell::sync::OnceCell;
54pub use request::{
55    Request, RequestBody as SyncRequestBody, RequestBuilder, RequestParts, RequestPartsBuilder, UserAgent,
56};
57pub use response::{
58    Metrics, MetricsBuilder, Response, ResponseBody as SyncResponseBody, ResponseBuilder, ResponseParts,
59    Result as ResponseResult,
60};
61use std::{
62    fmt::Debug,
63    io::{Result as IoResult, Seek},
64};
65
66/// 阻塞 HTTP 响应
67pub type SyncRequest<'r> = Request<'r, SyncRequestBody<'r>>;
68/// 阻塞 HTTP 响应构建器
69pub type SyncRequestBuilder<'r> = RequestBuilder<'r, SyncRequestBody<'r>>;
70
71/// 阻塞 HTTP 响应
72pub type SyncResponse = Response<SyncResponseBody>;
73/// 阻塞 HTTP 响应构建器
74pub type SyncResponseBuilder = ResponseBuilder<SyncResponseBody>;
75/// 阻塞 HTTP 响应结果
76pub type SyncResponseResult = ResponseResult<SyncResponseBody>;
77
78#[cfg(feature = "async")]
79mod async_req_resp {
80    pub use super::{request::AsyncRequestBody, response::AsyncResponseBody};
81    use super::{
82        request::{Request, RequestBuilder},
83        response::{Response, ResponseBuilder, Result as ResponseResult},
84    };
85
86    /// 异步 HTTP 响应
87    pub type AsyncRequest<'r> = Request<'r, AsyncRequestBody<'r>>;
88    /// 异步 HTTP 响应构建器
89    pub type AsyncRequestBuilder<'r> = RequestBuilder<'r, AsyncRequestBody<'r>>;
90
91    /// 异步 HTTP 响应
92    #[cfg_attr(feature = "docs", doc(cfg(feature = "async")))]
93    pub type AsyncResponse = Response<AsyncResponseBody>;
94
95    /// 异步 HTTP 响应构建器
96    #[cfg_attr(feature = "docs", doc(cfg(feature = "async")))]
97    pub type AsyncResponseBuilder = ResponseBuilder<AsyncResponseBody>;
98
99    /// 异步 HTTP 响应结果
100    #[cfg_attr(feature = "docs", doc(cfg(feature = "async")))]
101    pub type AsyncResponseResult = ResponseResult<AsyncResponseBody>;
102}
103
104#[cfg(feature = "async")]
105pub use {
106    async_req_resp::{
107        AsyncRequest, AsyncRequestBody, AsyncRequestBuilder, AsyncResponse, AsyncResponseBody, AsyncResponseBuilder,
108        AsyncResponseResult,
109    },
110    futures_lite::{AsyncRead, AsyncSeek},
111};
112
113#[cfg(feature = "async")]
114use std::{future::Future, pin::Pin};
115
116#[cfg(feature = "async")]
117type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + 'a + Send>>;
118
119static LIBRARY_USER_AGENT: OnceCell<UserAgent> = OnceCell::new();
120
121/// 全局设置库 UserAgent
122///
123/// 通常提供给封装七牛 SDK 的库使用,可以将库名称及版本号写入,方便之后进行调试
124///
125/// 该方法只能调用一次,一旦调用,全局生效
126///
127/// 每个请求的 UserAgent 由七牛 SDK 固定 UserAgent + 库 UserAgent + 请求的追加 UserAgent 三部分组成
128#[allow(clippy::result_large_err)]
129pub fn set_library_user_agent(user_agent: UserAgent) -> Result<(), UserAgent> {
130    LIBRARY_USER_AGENT.set(user_agent)
131}
132
133/// HTTP 请求处理接口
134///
135/// 实现该接口,即可处理所有七牛 SDK 发送的 HTTP 请求
136#[auto_impl(&, &mut, Box, Rc, Arc)]
137pub trait HttpCaller: Debug + Send + Sync {
138    /// 阻塞发送 HTTP 请求
139    ///
140    /// 该方法的异步版本为 [`Self::async_call`]。
141    fn call(&self, request: &mut SyncRequest<'_>) -> SyncResponseResult;
142
143    /// 异步发送 HTTP 请求
144    #[cfg(feature = "async")]
145    #[cfg_attr(feature = "docs", doc(cfg(feature = "async")))]
146    fn async_call<'a>(&'a self, request: &'a mut AsyncRequest<'_>) -> BoxFuture<'a, AsyncResponseResult>;
147
148    /// 是否实现了 IP 地址解析功能
149    #[inline]
150    fn is_resolved_ip_addrs_supported(&self) -> bool {
151        false
152    }
153
154    /// 是否返回响应指标信息功能
155    #[inline]
156    fn is_response_metrics_supported(&self) -> bool {
157        false
158    }
159}
160
161/// 重置输入流接口
162///
163/// 该接口相当于实现 `seek(SeekFrom::Start(0))`
164pub trait Reset {
165    /// 重置输入流
166    ///
167    /// 相当于 `seek(SeekFrom::Start(0))`
168    fn reset(&mut self) -> IoResult<()>;
169}
170
171impl<T: Seek> Reset for T {
172    #[inline]
173    fn reset(&mut self) -> IoResult<()> {
174        self.rewind()?;
175        Ok(())
176    }
177}
178
179/// 异步重置输入流接口
180///
181/// 该接口相当于实现 `seek(SeekFrom::Start(0))`
182#[cfg(feature = "async")]
183#[cfg_attr(feature = "docs", doc(cfg(feature = "async")))]
184pub trait AsyncReset {
185    /// 异步重置输入流
186    ///
187    /// 相当于 `seek(SeekFrom::Start(0))`
188    fn reset(&mut self) -> BoxFuture<IoResult<()>>;
189}
190
191#[cfg(feature = "async")]
192impl<T: AsyncSeek + Unpin + Send + Sync> AsyncReset for T {
193    #[inline]
194    fn reset(&mut self) -> BoxFuture<IoResult<()>> {
195        use std::io::SeekFrom;
196        use futures_lite::io::AsyncSeekExt;
197
198        Box::pin(async move {
199            self.seek(SeekFrom::Start(0)).await?;
200            Ok(())
201        })
202    }
203}
204
205/// 将所有 Trait 全部重新导出,方便统一导入
206pub mod prelude {
207    pub use super::{HttpCaller, Metrics, Reset};
208
209    #[cfg(feature = "async")]
210    pub use super::AsyncReset;
211}