1# ylong_http 用户指南 2 3ylong_http 提供了 HTTP 各个版本下的协议所需的各种基础组件和扩展组件,方便用户组织所需的 HTTP 结构。 4 5ylong_http 整体分为 2 个库: 6 7- ylong_http_client 库:HTTP 客户端库 8- ylong_http 库:HTTP 协议及组件库 9 10其中 ylong_http_client 库提供了 HTTP 客户端的功能,ylong_http 库提供了 HTTP 协议的基础组件。 11 12如果需要查看详细的接口说明请查看对应接口的 docs,可以使用 `cargo doc --open` 生成并查看 docs。 13 14## ylong_http_client 15 16用户可以使用 ylong_http_client 库来创建自定义的客户端。 17 18用户可以使用自定义客户端来向指定服务端发送请求,然后接收响应。 19 20在使用 ylong_http_client 的功能之前,请保证在 `BUILD.gn` 或 `Cargo.toml` 中已成功添加依赖并开启对应 feature。 21 22当前支持的功能: 23 24- 支持异步 HTTP 客户端创建 25- 支持 HTTP/1.1 26- 支持 HTTPS 27- 支持上传下载回调 28- 支持简单的 Mime 格式传输 29 30#### 创建一个异步客户端 31 32用户可以使用 `ylong_http_client::async_impl::Client` 来生成一个异步 HTTP 客户端。该功能被 feature `async` 控制。 33 34用户可以使用 `Client::new()` 直接生成默认配置的客户端: 35 36```rust 37use ylong_http_client::async_impl::Client; 38 39async fn create_default_client() { 40 // 创建一个默认配置选项的客户端。 41 let _client_default = Client::new(); 42} 43``` 44 45用户也可以使用 `Client::builder()` 自定义客户端: 46 47```rust 48use ylong_http_client::async_impl::Client; 49use ylong_http_client::Timeout; 50 51async fn create_client_with_builder() { 52 let _client_with_builder = Client::builder() // 创建 builder。 53 .connect_timeout(Timeout::from_secs(3)) // 设置一些自定义选项。 54 .request_timeout(Timeout::from_secs(3)) 55 .build(); // 构建 Client。 56} 57``` 58 59当前版本提供的 Client 的配置选项: 60 61- `connect_timeout`: 设置连接超时时间 62- `request_timeout`: 设置请求超时时间 63- `redirect`: 设置重定向逻辑 64- `proxy`: 设置代理逻辑 65- `tls_built_in_root_certs`: 是否使用预置证书 66- `add_root_certificate`: 设置根证书 67- `min_tls_version`: 设置 TLS 版本下限 68- `max_tls_version`: 设置 TLS 版本上限 69- `set_cipher_suite`: 设置 TLSv1.3 的算法套件 70- `set_cipher_list`: 设置 TLSv1.3 之前版本的算法套件 71- `set_ca_file`: 设置 CA 证书文件路径 72 73#### 创建请求 74 75用户可以使用 `Request` 结构提供的快速接口来生成 HTTP 请求。 76 77```rust 78use ylong_http_client::Request; 79 80async fn create_default_request() { 81 // 创建一个为 url 为 127.0.0.1:3000,body 为空的 GET 请求。 82 let _request_default = Request::get("127.0.0.1:3000").body("".as_bytes()).unwrap(); 83} 84``` 85 86用户也可以利用 `Request::builder()` 来自定义请求。 87 88```rust 89use ylong_http_client::{Request, Method}; 90 91async fn create_request_with_builder() { 92 let _request_with_builder = Request::builder() // 创建 RequestBuilder 93 .method(Method::GET) // 设置 Method 94 .url("http://www.example.com") // 设置 Url 95 .header("Content-Type", "application/octet-stream") // 设置 Header 96 .body("".as_bytes()); // 设置 body 97} 98``` 99 100当前版本提供的 Request 的配置选项: 101 102- `method`: 设置请求方法 103- `url`: 设置 Url 104- `header`: 插入请求头字段 105- `append_header`: 追加请求头字段 106- `body`: 设置一般 body 内容 107- `multipart`: 设置 multipart 格式 body 内容 108 109用户可以创建 Multipart 格式的请求: 110 111```rust 112use ylong_http_client::async_impl::{Multipart, Part}; 113use ylong_http_client::Request; 114 115async fn create_multipart() { 116 // 创建单个 part 117 let part = Part::new() 118 .mime("application/octet-stream") 119 .name("name") 120 .file_name("file_name") 121 .length(Some(10)) 122 .body("HelloWorld"); 123 124 // 创建 Multipart。 125 let multipart = MultiPart::new().part(part); 126 127 // 使用 multipart 接口创建 Request。 128 let _request = Request::get("127.0.0.1:3000").multipart(multipart); 129} 130``` 131 132用户可以在 body 的基础上,使用 `Uploader` 对上传逻辑进行控制: 133 134```rust 135use ylong_http_client::async_impl::Uploader; 136use ylong_http_client::Response; 137 138async fn create_uploader() { 139 // 创建输出到控制台的 Uploader。 140 let _uploader = Uploader::console("HelloWorld".as_bytes()); 141} 142``` 143 144```rust 145use std::pin::Pin; 146use std::task::{Context, Poll}; 147use ylong_http_client::async_impl::{Uploader, UploadOperator}; 148use ylong_http_client::HttpClientError; 149 150async fn upload_and_show_progress() { 151 // 自定义的 `UploadOperator`. 152 struct MyUploadOperator; 153 154 impl UploadOperator for MyUploadOperator { 155 fn poll_progress( 156 self: Pin<&mut Self>, 157 cx: &mut Context<'_>, 158 uploaded: u64, 159 total: Option<u64> 160 ) -> Poll<Result<(), HttpClientError>> { 161 todo!() 162 } 163 } 164 165 // 根据自定义的 Operator 创建 Uploader。 166 let uploader = Uploader::builder().reader("HelloWorld".as_bytes()).operator(MyUploadOperator).build(); 167} 168``` 169 170#### 发送请求、等待响应 171 172创建好 `Client` 和 `Request` 后即可利用 `Client::request` 接口发送请求并等待响应。 173 174```rust 175use ylong_http_client::async_impl::Client; 176use ylong_http_client::Request; 177 178async fn send_request<T>(client: Client, request: Request<T>) { 179 // 发送请求,等待响应。 180 let _response = client.request(request).await.unwrap(); 181} 182``` 183 184得到的响应会以 `Response` 结构的形式返回。响应的头字段会被完整地解析在 `Response` 结构体中, 185但是 body 部分需要用户根据自身需求在后续逻辑中读取。 186 187#### 读取响应 body 188 189得到 `Response` 后,可以对响应的 body 信息读取。 190 191用户可以通过调用 `Response::body_mut()`,获取到 body,再使用 `Body::data()` 自行读取 body 内容。 192 193```rust 194use ylong_http_client::async_impl::Body; 195use ylong_http_client::{Response, HttpClientError}; 196 197async fn receive_response_body(mut response: Response) -> Result<(), HttpClientError> { 198 let mut buf = [0u8; 1024]; 199 loop { 200 let size = response.body_mut().data(&mut buf).await?; 201 if size == 0 { 202 return Ok(()) 203 } 204 let data = &buf[..size]; 205 // 处理接收到的 data 信息。 206 } 207} 208``` 209 210使用 `Downloader` 可以进行一个更加灵活的下载方式。 211 212`Downloader` 提供一个直接将 body 输出到控制台的简单方式: 213 214```rust 215use ylong_http_client::async_impl::{Downloader, HttpBody, Response}; 216 217async fn download_and_show_progress_on_console(response: Response) { 218 // 将 Response body 打印到控制台,以字节方式打印。 219 let _ = Downloader::console(response).download().await; 220} 221``` 222 223用户也可以自定义 `Downloader` 中的 `DownloadOperator` 组件来实现灵活的自定义下载操作。 224 225用户需要给自身结构体实现 `DownloadOperator` trait,实现其中的 `poll_download` 和 226`poll_progress` 方法,以实现下载和显示回调功能。 227 228```rust 229use std::pin::Pin; 230use std::task::{Context, Poll}; 231use ylong_http_client::async_impl::{Downloader, DownloadOperatorResponse}; 232use ylong_http_client::{HttpClientError, SpeedLimit, Timeout}; 233 234async fn download_and_show_progress(response: Response) { 235 // 自定义的 `DownloadOperator`. 236 struct MyDownloadOperator; 237 238 // 为自定义结构实现 DownloadOperator。 239 impl DownloadOperator for MyDownloadOperator { 240 fn poll_download( 241 self: Pin<&mut Self>, 242 cx: &mut Context<'_>, 243 data: &[u8], 244 ) -> Poll<Result<usize, HttpClientError>> { 245 // 自定义 download 函数,每次从 Response 中读取到 data 后都会自动调用该接口。 246 todo!() 247 } 248 249 fn poll_progress( 250 self: Pin<&mut Self>, 251 cx: &mut Context<'_>, 252 downloaded: u64, 253 total: Option<u64> 254 ) -> Poll<Result<(), HttpClientError>> { 255 // 自定义 progress 函数,每次从 Response 中读取到 data 并处理后会调用该接口进行显示回调。 256 todo!() 257 } 258 } 259 260 // 创建 Downloader 对指定 Response 进行下载。 261 let mut downloader = Downloader::builder() 262 .body(response) // 设置 response 263 .operator(MyDownloadOperator) // 设置 operator 264 .build(); 265 let _ = downloader.download().await; 266} 267```