From 7af7462c18d14557b3024e417402aa89adbf6e86 Mon Sep 17 00:00:00 2001 From: fqwert Date: Thu, 20 Jul 2023 17:24:25 +0800 Subject: [PATCH] add rustfmt.toml and reformat Signed-off-by: fqwert --- rustfmt.toml | 6 + ylong_http/src/body/chunk.rs | 171 ++++++++----- ylong_http/src/body/empty.rs | 16 +- ylong_http/src/body/mime/common/headers.rs | 49 ++-- ylong_http/src/body/mime/common/mix.rs | 65 ++--- ylong_http/src/body/mime/common/mod.rs | 36 +-- ylong_http/src/body/mime/common/multi.rs | 36 ++- ylong_http/src/body/mime/common/part.rs | 46 ++-- ylong_http/src/body/mime/decode/multi.rs | 72 +++--- ylong_http/src/body/mime/decode/part.rs | 46 ++-- ylong_http/src/body/mime/encode/multi.rs | 59 ++--- ylong_http/src/body/mime/encode/part.rs | 54 ++--- ylong_http/src/body/mime/mime_test_macro.rs | 7 +- ylong_http/src/body/mime/mimetype.rs | 22 +- ylong_http/src/body/mime/mod.rs | 33 ++- ylong_http/src/body/mod.rs | 39 +-- ylong_http/src/body/text.rs | 32 ++- ylong_http/src/error.rs | 6 +- ylong_http/src/h1/mod.rs | 1 - ylong_http/src/h1/request/encoder.rs | 52 ++-- ylong_http/src/h1/response/decoder.rs | 75 +++--- ylong_http/src/h2/decoder.rs | 87 ++++--- ylong_http/src/h2/encoder.rs | 224 ++++++++++++------ ylong_http/src/h2/error.rs | 12 +- ylong_http/src/h2/frame.rs | 98 +++++--- ylong_http/src/h2/hpack/decoder.rs | 9 +- ylong_http/src/h2/hpack/integer.rs | 15 +- ylong_http/src/h2/hpack/mod.rs | 4 +- .../src/h2/hpack/representation/decoder.rs | 3 +- .../src/h2/hpack/representation/encoder.rs | 8 +- ylong_http/src/h2/hpack/representation/mod.rs | 23 +- ylong_http/src/h2/hpack/table.rs | 31 ++- ylong_http/src/h2/mod.rs | 1 - ylong_http/src/h2/pseudo.rs | 28 ++- ylong_http/src/headers.rs | 73 ++++-- ylong_http/src/huffman/mod.rs | 14 +- ylong_http/src/lib.rs | 2 - ylong_http/src/request/method.rs | 6 +- ylong_http/src/request/mod.rs | 40 ++-- ylong_http/src/request/uri.rs | 21 +- ylong_http/src/response/mod.rs | 10 +- ylong_http/src/response/status.rs | 3 +- ylong_http/src/version.rs | 6 +- ylong_http_client/examples/async_http.rs | 5 +- ylong_http_client/examples/async_http2.rs | 5 +- .../examples/async_http2_multi.rs | 6 +- .../examples/async_proxy_http.rs | 5 +- .../examples/async_redirect_http.rs | 5 +- ylong_http_client/examples/sync_http.rs | 5 +- ylong_http_client/examples/sync_proxy_http.rs | 5 +- .../examples/sync_redirect_http.rs | 5 +- ylong_http_client/src/async_impl/adapter.rs | 10 +- ylong_http_client/src/async_impl/client.rs | 53 ++--- .../src/async_impl/conn/http1.rs | 13 +- .../src/async_impl/conn/http2.rs | 27 ++- ylong_http_client/src/async_impl/conn/mod.rs | 10 +- ylong_http_client/src/async_impl/connector.rs | 20 +- .../src/async_impl/downloader/builder.rs | 13 +- .../src/async_impl/downloader/mod.rs | 10 +- .../src/async_impl/downloader/operator.rs | 9 +- ylong_http_client/src/async_impl/http_body.rs | 22 +- ylong_http_client/src/async_impl/mod.rs | 11 +- ylong_http_client/src/async_impl/pool.rs | 15 +- .../src/async_impl/ssl_stream/c_ssl_stream.rs | 28 +-- .../src/async_impl/ssl_stream/mix.rs | 7 +- .../src/async_impl/ssl_stream/mod.rs | 1 - .../src/async_impl/ssl_stream/wrapper.rs | 18 +- ylong_http_client/src/async_impl/timeout.rs | 7 +- .../src/async_impl/uploader/builder.rs | 18 +- .../src/async_impl/uploader/mod.rs | 20 +- .../src/async_impl/uploader/operator.rs | 5 +- ylong_http_client/src/error.rs | 3 +- ylong_http_client/src/lib.rs | 42 ++-- ylong_http_client/src/sync_impl/client.rs | 53 ++--- ylong_http_client/src/sync_impl/conn/http1.rs | 13 +- ylong_http_client/src/sync_impl/conn/mod.rs | 8 +- ylong_http_client/src/sync_impl/connector.rs | 22 +- ylong_http_client/src/sync_impl/http_body.rs | 15 +- ylong_http_client/src/sync_impl/mod.rs | 4 +- ylong_http_client/src/sync_impl/pool.rs | 9 +- ylong_http_client/src/sync_impl/reader.rs | 33 ++- ylong_http_client/src/sync_impl/ssl_stream.rs | 3 +- ylong_http_client/src/util/base64.rs | 5 +- .../src/util/c_openssl/adapter.rs | 74 +++--- ylong_http_client/src/util/c_openssl/bio.rs | 30 +-- ylong_http_client/src/util/c_openssl/error.rs | 23 +- .../src/util/c_openssl/ffi/bio.rs | 5 +- .../src/util/c_openssl/ffi/err.rs | 6 +- .../src/util/c_openssl/ffi/mod.rs | 3 +- .../src/util/c_openssl/ffi/pem.rs | 4 +- .../src/util/c_openssl/ffi/ssl.rs | 79 +++--- ylong_http_client/src/util/c_openssl/mod.rs | 14 +- .../src/util/c_openssl/ssl/ctx.rs | 58 +++-- .../src/util/c_openssl/ssl/error.rs | 6 +- .../src/util/c_openssl/ssl/ssl_base.rs | 43 ++-- .../src/util/c_openssl/ssl/stream.rs | 31 ++- ylong_http_client/src/util/c_openssl/stack.rs | 13 +- ylong_http_client/src/util/c_openssl/x509.rs | 36 ++- ylong_http_client/src/util/config/http.rs | 24 +- ylong_http_client/src/util/config/mod.rs | 11 +- ylong_http_client/src/util/config/settings.rs | 30 ++- .../src/util/config/tls/alpn/mod.rs | 8 +- ylong_http_client/src/util/dispatcher.rs | 115 +++++---- ylong_http_client/src/util/mod.rs | 6 +- ylong_http_client/src/util/normalizer.rs | 3 +- ylong_http_client/src/util/pool.rs | 5 +- ylong_http_client/src/util/proxy.rs | 16 +- ylong_http_client/src/util/redirect.rs | 13 +- ylong_http_client/tests/common/async_utils.rs | 1 + ylong_http_client/tests/common/mod.rs | 20 +- ylong_http_client/tests/sdv_async_http.rs | 5 +- .../tests/sdv_async_https_c_ssl.rs | 7 +- ylong_http_client/tests/sdv_sync_http.rs | 5 +- .../tests/sdv_sync_https_c_ssl.rs | 6 +- 114 files changed, 1655 insertions(+), 1254 deletions(-) create mode 100644 rustfmt.toml diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..758f41a --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,6 @@ +edition = "2021" +wrap_comments = true +imports_granularity = "Module" +group_imports = "StdExternalCrate" +format_code_in_doc_comments = true +normalize_comments = true diff --git a/ylong_http/src/body/chunk.rs b/ylong_http/src/body/chunk.rs index ba51b3b..c711531 100644 --- a/ylong_http/src/body/chunk.rs +++ b/ylong_http/src/body/chunk.rs @@ -11,12 +11,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::origin::{FromAsyncReader, FromBytes, FromReader}; -use super::{async_impl, sync_impl}; -use crate::body::origin::FromAsyncBody; -use crate::error::{ErrorKind, HttpError}; -use crate::headers::{Header, HeaderName, HeaderValue, Headers}; -use crate::{AsyncRead, AsyncReadExt, ReadBuf}; use core::convert::Infallible; use core::ops::{Deref, DerefMut}; use core::pin::Pin; @@ -28,16 +22,24 @@ use std::convert::{TryFrom, TryInto}; use std::future::Future; use std::io::{Error, Read}; -/// A chunk body is used to encode body to send message by chunk in `HTTP/1.1` format. +use super::origin::{FromAsyncReader, FromBytes, FromReader}; +use super::{async_impl, sync_impl}; +use crate::body::origin::FromAsyncBody; +use crate::error::{ErrorKind, HttpError}; +use crate::headers::{Header, HeaderName, HeaderValue, Headers}; +use crate::{AsyncRead, AsyncReadExt, ReadBuf}; + +/// A chunk body is used to encode body to send message by chunk in `HTTP/1.1` +/// format. /// -/// This chunk body encoder supports you to use the chunk encode method multiple times to output -/// the result in multiple bytes slices. +/// This chunk body encoder supports you to use the chunk encode method multiple +/// times to output the result in multiple bytes slices. /// /// # Examples /// /// ``` -/// use ylong_http::body::ChunkBody; /// use ylong_http::body::sync_impl::Body; +/// use ylong_http::body::ChunkBody; /// /// let content = "aaaaa bbbbb ccccc ddddd"; /// // Gets `ChunkBody` @@ -87,15 +89,20 @@ struct StatusVar { // Data encoding status enum DataState { - Partial, // Data encode is processing - Complete, // Data encode is completed - Finish, // Data encode is finished and return result + // Data encode is processing + Partial, + // Data encode is completed + Complete, + // Data encode is finished and return result + Finish, } // Component encoding status enum TokenStatus { - Complete(T), // The current component is completely encoded. - Partial(E), // The current component is partially encoded. + // The current component is completely encoded. + Complete(T), + // The current component is partially encoded. + Partial(E), } type Token = TokenStatus; @@ -759,7 +766,8 @@ impl ChunkExt { } /// Decode state of the chunk buffer. -/// When chunks in the buffer end in different elements, `ChunkBodyDecoder` returns different `ChunkState`, as shown in the following figure: +/// When chunks in the buffer end in different elements, `ChunkBodyDecoder` +/// returns different `ChunkState`, as shown in the following figure: /// > ```trust /// > Meta: `chunk-size [ chunk-ext ] CRLF` /// > Partial: `chunk-size [ chunk-ext ] CRLF chunk-data` @@ -864,9 +872,9 @@ impl<'a> IntoIterator for Chunks<'a> { } /// Chunk instance, Indicates a chunk. -/// After a decode, the `ChunkBodyDecoder` returns a `Chunk` regardless of whether a chunk is completely decoded. -/// The decode status is recorded by the `state` variable. -/// +/// After a decode, the `ChunkBodyDecoder` returns a `Chunk` regardless of +/// whether a chunk is completely decoded. The decode status is recorded by the +/// `state` variable. #[derive(Debug, Eq, PartialEq)] pub struct Chunk<'a> { id: usize, @@ -897,7 +905,8 @@ impl Chunk<'_> { } /// Get the size of chunk-data, - /// If the size part of a chunk is not completely decoded, the value of size is 0. + /// If the size part of a chunk is not completely decoded, the value of size + /// is 0. pub fn size(&self) -> usize { self.size } @@ -920,9 +929,10 @@ impl Chunk<'_> { } /// Chunk decoder. -/// The decoder decode only all chunks and last-chunk in chunk-body and does not decode subsequent trailer-section. -/// The decoder maintains a state saving decode phase. -/// When a chunk is not completely decoded or a decoding exception occurs, the state is not reset. +/// The decoder decode only all chunks and last-chunk in chunk-body and does not +/// decode subsequent trailer-section. The decoder maintains a state saving +/// decode phase. When a chunk is not completely decoded or a decoding exception +/// occurs, the state is not reset. pub struct ChunkBodyDecoder { chunk_num: usize, total_size: usize, @@ -967,9 +977,10 @@ impl ChunkBodyDecoder { } /// Decode interface of the chunk decoder. - /// It transfers a u8 slice pointing to the chunk data and returns the data of a chunk and the remaining data. - /// When the data in the u8 slice is not completely decoded for a chunk, - /// An empty u8 slice is returned for the remaining data. + /// It transfers a u8 slice pointing to the chunk data and returns the data + /// of a chunk and the remaining data. When the data in the u8 slice is + /// not completely decoded for a chunk, An empty u8 slice is returned + /// for the remaining data. /// /// # Examples /// @@ -982,13 +993,25 @@ impl ChunkBodyDecoder { /// 000; message = last\r\n\ /// \r\n\ /// " - /// .as_bytes(); + /// .as_bytes(); /// let (chunks, rest) = decoder.decode(chunk_body_bytes).unwrap(); /// assert_eq!(chunks.iter().len(), 2); /// let chunk = chunks.iter().next().unwrap(); /// assert_eq!( - /// (chunk.id(), chunk.state(), chunk.size(), chunk.extension(), chunk.data()), - /// (0, &ChunkState::Finish, 5, &ChunkExt::new(), "hello".as_bytes()) + /// ( + /// chunk.id(), + /// chunk.state(), + /// chunk.size(), + /// chunk.extension(), + /// chunk.data() + /// ), + /// ( + /// 0, + /// &ChunkState::Finish, + /// 5, + /// &ChunkExt::new(), + /// "hello".as_bytes() + /// ) /// ); /// ``` pub fn decode<'a>(&mut self, buf: &'a [u8]) -> Result<(Chunks<'a>, &'a [u8]), HttpError> { @@ -1185,7 +1208,8 @@ impl ChunkBodyDecoder { match b { b'\r' => { if self.cr_meet { - // TODO Check whether the state machine needs to be reused after the parsing fails and whether the state machine status needs to be adjusted. + // TODO Check whether the state machine needs to be reused after the parsing + // fails and whether the state machine status needs to be adjusted. return Err(ErrorKind::InvalidInput.into()); } self.cr_meet = true; @@ -1615,7 +1639,8 @@ mod ut_chunk { \r\n\ " .as_bytes(); - let res = decoder.decode(&chunk_body_bytes[..1]); // 5 + // 5 + let res = decoder.decode(&chunk_body_bytes[..1]); let mut chunks = Chunks::new(); chunks.push(Chunk { id: 0, @@ -1626,8 +1651,8 @@ mod ut_chunk { trailer: None, }); assert_eq!(res, Ok((chunks, &[] as &[u8],))); - - let res = decoder.decode(&chunk_body_bytes[1..2]); // 5\r + // 5\r + let res = decoder.decode(&chunk_body_bytes[1..2]); let mut chunks = Chunks::new(); chunks.push(Chunk { id: 0, @@ -1638,8 +1663,8 @@ mod ut_chunk { trailer: None, }); assert_eq!(res, Ok((chunks, &[] as &[u8],))); - - let res = decoder.decode(&chunk_body_bytes[2..2]); // 5\r + // 5\r + let res = decoder.decode(&chunk_body_bytes[2..2]); let mut chunks = Chunks::new(); chunks.push(Chunk { id: 0, @@ -1650,8 +1675,8 @@ mod ut_chunk { trailer: None, }); assert_eq!(res, Ok((chunks, &[] as &[u8],))); - - let res = decoder.decode(&chunk_body_bytes[2..3]); // 5\r\n + // 5\r\n + let res = decoder.decode(&chunk_body_bytes[2..3]); let mut chunks = Chunks::new(); chunks.push(Chunk { id: 0, @@ -1663,7 +1688,8 @@ mod ut_chunk { }); assert_eq!(res, Ok((chunks, &[] as &[u8],))); - let res = decoder.decode(&chunk_body_bytes[3..5]); // 5\r\nhe + // 5\r\nhe + let res = decoder.decode(&chunk_body_bytes[3..5]); let mut chunks = Chunks::new(); chunks.push(Chunk { id: 0, @@ -1675,7 +1701,8 @@ mod ut_chunk { }); assert_eq!(res, Ok((chunks, &[] as &[u8],))); - let res = decoder.decode(&chunk_body_bytes[5..9]); // 5\r\nhello\r + // 5\r\nhello\r + let res = decoder.decode(&chunk_body_bytes[5..9]); let mut chunks = Chunks::new(); chunks.push(Chunk { id: 0, @@ -1687,7 +1714,8 @@ mod ut_chunk { }); assert_eq!(res, Ok((chunks, &[] as &[u8],))); - let res = decoder.decode(&chunk_body_bytes[9..9]); // 5\r\nhello\r + // 5\r\nhello\r + let res = decoder.decode(&chunk_body_bytes[9..9]); let mut chunks = Chunks::new(); chunks.push(Chunk { id: 0, @@ -1699,7 +1727,8 @@ mod ut_chunk { }); assert_eq!(res, Ok((chunks, &[] as &[u8],))); - let res = decoder.decode(&chunk_body_bytes[9..10]); // 5\r\nhello\r\n + // 5\r\nhello\r\n + let res = decoder.decode(&chunk_body_bytes[9..10]); let mut chunks = Chunks::new(); chunks.push(Chunk { id: 0, @@ -1711,7 +1740,8 @@ mod ut_chunk { }); assert_eq!(res, Ok((chunks, &[] as &[u8],))); - let res = decoder.decode(&chunk_body_bytes[10..13]); // 5\r\nhello\r\nC ; + // 5\r\nhello\r\nC ; + let res = decoder.decode(&chunk_body_bytes[10..13]); let mut chunks = Chunks::new(); chunks.push(Chunk { id: 1, @@ -1723,7 +1753,8 @@ mod ut_chunk { }); assert_eq!(res, Ok((chunks, &[] as &[u8],))); - let res = decoder.decode(&chunk_body_bytes[13..27]); // 5\r\nhello\r\nC ; type = text ; + // 5\r\nhello\r\nC ; type = text ; + let res = decoder.decode(&chunk_body_bytes[13..27]); let mut chunks = Chunks::new(); chunks.push(Chunk { id: 1, @@ -1735,7 +1766,8 @@ mod ut_chunk { }); assert_eq!(res, Ok((chunks, &[] as &[u8],))); - let res = decoder.decode(&chunk_body_bytes[27..36]); // 5\r\nhello\r\nC ; type = text ;end = !\r\n + // 5\r\nhello\r\nC ; type = text ;end = !\r\n + let res = decoder.decode(&chunk_body_bytes[27..36]); let mut chunks = Chunks::new(); chunks.push(Chunk { id: 1, @@ -1747,7 +1779,8 @@ mod ut_chunk { }); assert_eq!(res, Ok((chunks, &[] as &[u8],))); - let res = decoder.decode(&chunk_body_bytes[36..50]); // 5\r\nhello\r\nC ; type = text ;end = !\r\nhello world!\r\n + // 5\r\nhello\r\nC ; type = text ;end = !\r\nhello world!\r\n + let res = decoder.decode(&chunk_body_bytes[36..50]); let mut chunks = Chunks::new(); chunks.push(Chunk { id: 1, @@ -1759,7 +1792,8 @@ mod ut_chunk { }); assert_eq!(res, Ok((chunks, &[] as &[u8],))); - let res = decoder.decode(&chunk_body_bytes[50..51]); // 5\r\nhello\r\nC ; type = text ;end = !\r\nhello world!\r\n0 + // 5\r\nhello\r\nC ; type = text ;end = !\r\nhello world!\r\n0 + let res = decoder.decode(&chunk_body_bytes[50..51]); let mut chunks = Chunks::new(); chunks.push(Chunk { id: 2, @@ -1771,7 +1805,8 @@ mod ut_chunk { }); assert_eq!(res, Ok((chunks, &[] as &[u8],))); - let res = decoder.decode(&chunk_body_bytes[51..54]); // 5\r\nhello\r\nC ; type = text ;end = !\r\nhello world!\r\n000; + // 5\r\nhello\r\nC ; type = text ;end = !\r\nhello world!\r\n000; + let res = decoder.decode(&chunk_body_bytes[51..54]); let mut chunks = Chunks::new(); chunks.push(Chunk { id: 2, @@ -1783,7 +1818,9 @@ mod ut_chunk { }); assert_eq!(res, Ok((chunks, &[] as &[u8],))); - let res = decoder.decode(&chunk_body_bytes[54..71]); // 5\r\nhello\r\nC ; type = text ;end = !\r\nhello world!\r\n000; message = last\r\n + // 5\r\nhello\r\nC ; type = text ;end = !\r\nhello world!\r\n000; message = + // last\r\n + let res = decoder.decode(&chunk_body_bytes[54..71]); let mut chunks = Chunks::new(); chunks.push(Chunk { id: 2, @@ -1794,8 +1831,9 @@ mod ut_chunk { trailer: Some(&[] as &[u8]), }); assert_eq!(res, Ok((chunks, &[] as &[u8]))); - - let res = decoder.decode(&chunk_body_bytes[71..87]); // 5\r\nhello\r\nC ; type = text ;end = !\r\nhello world!\r\n000; message = last\r\nTrailer: value\r\n + // 5\r\nhello\r\nC ; type = text ;end = !\r\nhello world!\r\n000; message = + // last\r\nTrailer: value\r\n + let res = decoder.decode(&chunk_body_bytes[71..87]); let mut chunks = Chunks::new(); chunks.push(Chunk { id: 3, @@ -1806,8 +1844,9 @@ mod ut_chunk { trailer: Some("Trailer: value".as_bytes()), }); assert_eq!(res, Ok((chunks, &[] as &[u8]))); - - let res = decoder.decode(&chunk_body_bytes[87..119]); // 5\r\nhello\r\nC ; type = text ;end = !\r\nhello world!\r\n000; message = last\r\nTrailer: value\r\n\another-trainer: another-value\r\n\ + // 5\r\nhello\r\nC ; type = text ;end = !\r\nhello world!\r\n000; + // message = last\r\nTrailer: value\r\n\another-trainer: another-value\r\n\ + let res = decoder.decode(&chunk_body_bytes[87..119]); let mut chunks = Chunks::new(); chunks.push(Chunk { id: 3, @@ -1818,8 +1857,9 @@ mod ut_chunk { trailer: Some("another-trainer: another-value".as_bytes()), }); assert_eq!(res, Ok((chunks, &[] as &[u8]))); - - let res = decoder.decode(&chunk_body_bytes[119..121]); // 5\r\nhello\r\nC ; type = text ;end = !\r\nhello world!\r\n000; message = last\r\nTrailer: value\r\n\another-trainer: another-value\r\n\r\n\ + // 5\r\nhello\r\nC ; type = text ;end = !\r\nhello world!\r\n000; + // message = last\r\nTrailer: value\r\n\another-trainer: another-value\r\n\r\n\ + let res = decoder.decode(&chunk_body_bytes[119..121]); let mut chunks = Chunks::new(); chunks.push(Chunk { id: 3, @@ -1850,7 +1890,9 @@ mod ut_chunk { \r\n\ " .as_bytes(); - let (chunks, remaining) = decoder.decode(chunk_body_bytes).unwrap(); // 5 + + // 5 + let (chunks, remaining) = decoder.decode(chunk_body_bytes).unwrap(); let mut iter = chunks.iter(); let chunk = Chunk { id: 0, @@ -1901,7 +1943,9 @@ mod ut_chunk { \r\n\ " .as_bytes(); - let (chunks, remaining) = decoder.decode(chunk_body_bytes).unwrap(); // 5 + + // 5 + let (chunks, remaining) = decoder.decode(chunk_body_bytes).unwrap(); let mut iter = chunks.into_iter(); let chunk = Chunk { id: 0, @@ -1950,7 +1994,9 @@ mod ut_chunk { " .as_bytes(); let mut decoder = ChunkBodyDecoder::new(); - let res = decoder.decode(chunk_body_bytes); // 5 + + // 5 + let res = decoder.decode(chunk_body_bytes); assert_eq!(res, Err(ErrorKind::InvalidInput.into())); } @@ -1972,7 +2018,9 @@ mod ut_chunk { " .as_bytes(); let mut decoder = ChunkBodyDecoder::new(); - let res = decoder.decode(chunk_body_bytes); // 5 + + // 5 + let res = decoder.decode(chunk_body_bytes); assert_eq!(res, Err(ErrorKind::InvalidInput.into())); } @@ -1993,7 +2041,8 @@ mod ut_chunk { " .as_bytes(); let mut decoder = ChunkBodyDecoder::new(); - let res = decoder.decode(chunk_body_bytes); // 5 + // 5 + let res = decoder.decode(chunk_body_bytes); assert_eq!(res, Err(ErrorKind::InvalidInput.into())); } @@ -2015,7 +2064,9 @@ mod ut_chunk { \r\n\ " .as_bytes(); - let (chunks, _) = decoder.decode(chunk_body_bytes).unwrap(); // 5 + + // 5 + let (chunks, _) = decoder.decode(chunk_body_bytes).unwrap(); assert_eq!(chunks.iter().len(), 3); let chunk = chunks.iter().next().unwrap(); assert_eq!( diff --git a/ylong_http/src/body/empty.rs b/ylong_http/src/body/empty.rs index 144541a..852677f 100644 --- a/ylong_http/src/body/empty.rs +++ b/ylong_http/src/body/empty.rs @@ -11,16 +11,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::body::{async_impl, sync_impl}; use core::convert::Infallible; use core::pin::Pin; use core::task::{Context, Poll}; +use crate::body::{async_impl, sync_impl}; + /// An empty body, indicating that there is no body part in the message. /// -/// `EmptyBody` both implements [`sync_impl::Body`] and [`async_impl::Body`]. Using -/// [`sync_impl::Body::data`] method or [`async_impl::Body::data`] method has no effect -/// on buf and always returns `Ok(0)`. +/// `EmptyBody` both implements [`sync_impl::Body`] and [`async_impl::Body`]. +/// Using [`sync_impl::Body::data`] method or [`async_impl::Body::data`] method +/// has no effect on buf and always returns `Ok(0)`. /// /// [`sync_impl::Body`]: sync_impl::Body /// [`async_impl::Body`]: async_impl::Body @@ -32,8 +33,8 @@ use core::task::{Context, Poll}; /// sync_impl: /// /// ``` -/// use ylong_http::body::EmptyBody; /// use ylong_http::body::sync_impl::Body; +/// use ylong_http::body::EmptyBody; /// /// let mut body = EmptyBody::new(); /// let mut buf = [0u8; 1024]; @@ -45,8 +46,8 @@ use core::task::{Context, Poll}; /// async_impl: /// /// ``` -/// use ylong_http::body::EmptyBody; /// use ylong_http::body::async_impl::Body; +/// use ylong_http::body::EmptyBody; /// /// # async fn read_empty_body() { /// let mut body = EmptyBody::new(); @@ -131,7 +132,8 @@ mod ut_empty { /// /// # Brief /// 1. Creates an `EmptyBody`. - /// 2. Calls its `async_impl::Body::data` method and then checks the results. + /// 2. Calls its `async_impl::Body::data` method and then checks the + /// results. #[cfg(feature = "tokio_base")] #[tokio::test] async fn ut_empty_body_async_impl_data() { diff --git a/ylong_http/src/body/mime/common/headers.rs b/ylong_http/src/body/mime/common/headers.rs index 5f069d5..db37a02 100644 --- a/ylong_http/src/body/mime/common/headers.rs +++ b/ylong_http/src/body/mime/common/headers.rs @@ -11,21 +11,18 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{ - body::{ - mime::{ - common::{consume_crlf, data_copy, trim_front_lwsp, BytesResult, TokenResult}, - CR, LF, - }, - TokenStatus, - }, - error::{ErrorKind, HttpError}, - h1::response::decoder::{HEADER_NAME_BYTES, HEADER_VALUE_BYTES}, - headers::{HeaderName, HeaderValue, Headers}, -}; use core::mem::take; use std::collections::hash_map::IntoIter; +use crate::body::mime::common::{ + consume_crlf, data_copy, trim_front_lwsp, BytesResult, TokenResult, +}; +use crate::body::mime::{CR, LF}; +use crate::body::TokenStatus; +use crate::error::{ErrorKind, HttpError}; +use crate::h1::response::decoder::{HEADER_NAME_BYTES, HEADER_VALUE_BYTES}; +use crate::headers::{HeaderName, HeaderValue, Headers}; + #[derive(Debug, PartialEq)] pub(crate) enum HeaderStatus { Start, @@ -172,7 +169,8 @@ impl DecodeHeaders { let rest = match self.stage { HeaderStatus::Start => self.start_decode(remains), HeaderStatus::Name => self.name_decode(remains), - HeaderStatus::Colon => Ok(remains), // not use + // not use + HeaderStatus::Colon => Ok(remains), HeaderStatus::Value => self.value_decode(remains), HeaderStatus::Crlf => self.crlf_decode(remains), HeaderStatus::End => { @@ -293,7 +291,8 @@ impl DecodeHeaders { fn get_header_name(buf: &[u8]) -> BytesResult { for (i, b) in buf.iter().enumerate() { if *b == b':' { - return Ok(TokenStatus::Complete((&buf[..i], &buf[i + 1..]))); // match "k:v" or "k: v" + // match "k:v" or "k: v" + return Ok(TokenStatus::Complete((&buf[..i], &buf[i + 1..]))); } else if !HEADER_NAME_BYTES[*b as usize] { return Err(ErrorKind::InvalidInput.into()); } @@ -316,10 +315,9 @@ impl DecodeHeaders { #[cfg(test)] mod ut_decode_headers { - use crate::{ - body::{mime::common::headers::DecodeHeaders, TokenStatus}, - headers::Headers, - }; + use crate::body::mime::common::headers::DecodeHeaders; + use crate::body::TokenStatus; + use crate::headers::Headers; /// UT test cases for `DecodeHeaders::decode`. /// @@ -456,19 +454,23 @@ mod ut_decode_headers { fn ut_decode_headers_decode3() { let buf = b"name1:value1\r\nname2:value2\r\n\r\naaaa"; let mut decoder = DecodeHeaders::new(); - let (headers, rest) = decoder.decode(&buf[0..3]).unwrap(); // nam + // nam + let (headers, rest) = decoder.decode(&buf[0..3]).unwrap(); assert_eq!(headers, TokenStatus::Partial(())); assert_eq!(std::str::from_utf8(rest).unwrap(), ""); - let (headers, rest) = decoder.decode(&buf[3..13]).unwrap(); // e1:value1\r + // e1:value1\r + let (headers, rest) = decoder.decode(&buf[3..13]).unwrap(); assert_eq!(headers, TokenStatus::Partial(())); assert_eq!(std::str::from_utf8(rest).unwrap(), ""); - let (headers, rest) = decoder.decode(&buf[13..29]).unwrap(); // \nname2:value2\r\n\r + // \nname2:value2\r\n\r + let (headers, rest) = decoder.decode(&buf[13..29]).unwrap(); assert_eq!(headers, TokenStatus::Partial(())); assert_eq!(std::str::from_utf8(rest).unwrap(), ""); - let (headers, rest) = decoder.decode(&buf[29..30]).unwrap(); // \n + // \n + let (headers, rest) = decoder.decode(&buf[29..30]).unwrap(); assert_eq!( headers, TokenStatus::Complete({ @@ -480,7 +482,8 @@ mod ut_decode_headers { ); assert_eq!(std::str::from_utf8(rest).unwrap(), ""); - let (headers, rest) = decoder.decode(&buf[30..34]).unwrap(); // aaaa + // aaaa + let (headers, rest) = decoder.decode(&buf[30..34]).unwrap(); assert_eq!(headers, TokenStatus::Complete(Headers::new())); assert_eq!(std::str::from_utf8(rest).unwrap(), "aaaa"); } diff --git a/ylong_http/src/body/mime/common/mix.rs b/ylong_http/src/body/mime/common/mix.rs index 1e1cc9e..6095f0a 100644 --- a/ylong_http/src/body/mime/common/mix.rs +++ b/ylong_http/src/body/mime/common/mix.rs @@ -11,25 +11,27 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::body::{ - async_impl::{self, DataFuture}, - mime::common::{data_copy, SizeResult, TokenStatus}, - sync_impl, -}; -use crate::{AsyncRead, ReadBuf}; -use core::{ - fmt::Debug, - pin::Pin, - task::{Context, Poll}, -}; +use core::fmt::Debug; +use core::pin::Pin; +use core::task::{Context, Poll}; use std::io::Read; -// Uses Box so that it can be put into a list(like vec) with different T. +use crate::body::async_impl::{self, DataFuture}; +use crate::body::mime::common::{data_copy, SizeResult, TokenStatus}; +use crate::body::sync_impl; +use crate::{AsyncRead, ReadBuf}; + +// Uses Box so that it can be put into a list(like vec) with +// different T. pub(crate) enum MixFrom<'a> { - Owned { bytes: Vec, index: usize }, // the read content is Vec - Slice { bytes: &'a [u8], index: usize }, // the read content is from memory - Reader(Box), // the read content is from a synchronous reader - AsyncReader(Box), // the read content is from an asynchronous reader + // the read content is Vec + Owned { bytes: Vec, index: usize }, + // the read content is from memory + Slice { bytes: &'a [u8], index: usize }, + // the read content is from a synchronous reader + Reader(Box), + // the read content is from an asynchronous reader + AsyncReader(Box), } impl<'a> MixFrom<'a> { @@ -135,7 +137,8 @@ impl Debug for MixFrom<'_> { } } -// It is not a complete implementation, only implements for MixFrom::Owned && MixFrom::Slice. +// It is not a complete implementation, only implements for MixFrom::Owned && +// MixFrom::Slice. impl PartialEq for MixFrom<'_> { fn eq(&self, other: &Self) -> bool { match (self, other) { @@ -214,7 +217,8 @@ impl async_impl::Body for MixFrom<'_> { #[cfg(test)] mod ut_mix { - use crate::body::{async_impl, mime::common::mix::MixFrom, sync_impl}; + use crate::body::mime::common::mix::MixFrom; + use crate::body::{async_impl, sync_impl}; /// Builds a `MixFrom`. macro_rules! mix_build { @@ -261,9 +265,9 @@ mod ut_mix { $(BodyAsyncReader: $body4,)? }, ); - + // default 1 #[allow(unused_assignments, unused_mut)] - let mut len = 1; // default 1 + let mut len = 1; $(len = $size;)? let mut buf = vec![0u8; len]; @@ -303,8 +307,9 @@ mod ut_mix { }, ); + // default 1 #[allow(unused_assignments, unused_mut)] - let mut len = 1; // default 1 + let mut len = 1; $(len = $size;)? let mut buf = vec![0u8; len]; @@ -376,7 +381,8 @@ mod ut_mix { /// UT test cases for `MixFrom::set_reader`. /// /// # Brief - /// 1. Creates a `MixFrom` from synchronous read content by `MixFrom::set_reader`. + /// 1. Creates a `MixFrom` from synchronous read content by + /// `MixFrom::set_reader`. /// 2. Checks whether the result is correct. #[test] fn ut_mix_set_reader() { @@ -392,7 +398,8 @@ mod ut_mix { /// UT test cases for `MixFrom::set_async_reader`. /// /// # Brief - /// 1. Creates a `MixFrom` from asynchronous read content by `MixFrom::set_async_reader`. + /// 1. Creates a `MixFrom` from asynchronous read content by + /// `MixFrom::set_async_reader`. /// 2. Encodes by synchronous encoding. /// 3. Checks whether the result is correct. #[test] @@ -409,7 +416,8 @@ mod ut_mix { /// UT test cases for `MixFrom::set_async_reader`. /// /// # Brief - /// 1. Creates a `MixFrom` from asynchronous read content by `MixFrom::set_async_reader`. + /// 1. Creates a `MixFrom` from asynchronous read content by + /// `MixFrom::set_async_reader`. /// 2. Encodes by asynchronous encoding. /// 3. Checks whether the result is correct. #[cfg(feature = "tokio_base")] @@ -427,7 +435,8 @@ mod ut_mix { /// UT test cases for `MixFrom::set_reader`. /// /// # Brief - /// 1. Creates a `MixFrom` from synchronous read content by `MixFrom::set_reader`. + /// 1. Creates a `MixFrom` from synchronous read content by + /// `MixFrom::set_reader`. /// 2. Encodes by asynchronous encoding. /// 3. Checks whether the result is correct. #[cfg(feature = "tokio_base")] @@ -445,7 +454,8 @@ mod ut_mix { /// UT test cases for `MixFrom::set_bytes`. /// /// # Brief - /// 1. Creates a `MixFrom` from synchronous read content by `MixFrom::set_bytes`. + /// 1. Creates a `MixFrom` from synchronous read content by + /// `MixFrom::set_bytes`. /// 2. Encodes by asynchronous encoding. /// 3. Checks whether the result is correct. #[cfg(feature = "tokio_base")] @@ -463,7 +473,8 @@ mod ut_mix { /// UT test cases for `MixFrom::set_owned`. /// /// # Brief - /// 1. Creates a `MixFrom` from synchronous read content by `MixFrom::set_owned`. + /// 1. Creates a `MixFrom` from synchronous read content by + /// `MixFrom::set_owned`. /// 2. Encodes by asynchronous encoding. /// 3. Checks whether the result is correct. #[cfg(feature = "tokio_base")] diff --git a/ylong_http/src/body/mime/common/mod.rs b/ylong_http/src/body/mime/common/mod.rs index a02679e..795a879 100644 --- a/ylong_http/src/body/mime/common/mod.rs +++ b/ylong_http/src/body/mime/common/mod.rs @@ -16,28 +16,30 @@ mod mix; mod multi; mod part; -pub use multi::{MimeMulti, MimeMultiBuilder, XPart}; -pub use part::{MimePart, MimePartBuilder}; - pub(crate) use headers::{DecodeHeaders, EncodeHeaders, HeaderStatus}; pub(crate) use mix::MixFrom; +pub use multi::{MimeMulti, MimeMultiBuilder, XPart}; pub(crate) use part::PartStatus; +pub use part::{MimePart, MimePartBuilder}; pub(crate) type SizeResult = Result; pub(crate) type TokenResult = Result, std::io::Error>; pub(crate) type BytesResult<'a> = Result, HttpError>; -use crate::{ - error::{ErrorKind, HttpError}, - headers::Headers, -}; use core::mem::take; use std::io::Read; +use crate::error::{ErrorKind, HttpError}; +use crate::headers::Headers; + // RFC5234 ABNF -pub(crate) const HTAB: u8 = b'\t'; // horizontal tab -pub(crate) const SP: u8 = b' '; // 0x20 space -pub(crate) const CR: u8 = b'\r'; // carriage return -pub(crate) const LF: u8 = b'\n'; // linefeed +// horizontal tab +pub(crate) const HTAB: u8 = b'\t'; +// 0x20 space +pub(crate) const SP: u8 = b' '; +// carriage return +pub(crate) const CR: u8 = b'\r'; +// linefeed +pub(crate) const LF: u8 = b'\n'; pub(crate) const CRLF: &[u8] = b"\r\n"; /// Represents component encoding/decoding status. @@ -67,11 +69,13 @@ impl TokenStatus { } } -// Pulls some bytes from this src into the buf, returning how many bytes were read. +// Pulls some bytes from this src into the buf, returning how many bytes were +// read. pub(crate) fn data_copy(src: &[u8], src_idx: &mut usize, buf: &mut [u8]) -> TokenResult { let input_len = src.len() - *src_idx; let output_len = buf.len(); - let num = (&src[*src_idx..]).read(buf)?; // sync + // sync + let num = (&src[*src_idx..]).read(buf)?; *src_idx += num; if output_len >= input_len { return Ok(TokenStatus::Complete(num)); @@ -116,7 +120,8 @@ pub(crate) fn trim_back_lwsp_if_end_with_lf(buf: &[u8]) -> &[u8] { // reduce "\n" or "\r\n" pub(crate) fn consume_crlf( buf: &[u8], - cr_meet: bool, //has "\r" + // has "\r" + cr_meet: bool, ) -> Result, HttpError> { if buf.is_empty() { return Ok(TokenStatus::Partial(0)); @@ -210,7 +215,8 @@ pub(crate) fn get_content_type_boundary(headers: &Headers) -> Option> { #[cfg(test)] mod ut_common { - use crate::{body::mime::common::get_content_type_boundary, headers::Headers}; + use crate::body::mime::common::get_content_type_boundary; + use crate::headers::Headers; /// UT test cases for `get_content_type_boundary`. /// diff --git a/ylong_http/src/body/mime/common/multi.rs b/ylong_http/src/body/mime/common/multi.rs index 27275b3..afcb0ac 100644 --- a/ylong_http/src/body/mime/common/multi.rs +++ b/ylong_http/src/body/mime/common/multi.rs @@ -11,13 +11,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::headers::{HeaderName, HeaderValue}; -use crate::{ - body::mime::{DecodeHeaders, MimePart}, - error::{ErrorKind, HttpError}, - headers::{Header, Headers}, -}; -use core::{convert::TryFrom, mem::take}; +use core::convert::TryFrom; +use core::mem::take; + +use crate::body::mime::{DecodeHeaders, MimePart}; +use crate::error::{ErrorKind, HttpError}; +use crate::headers::{Header, HeaderName, HeaderValue, Headers}; /// `MimeMulti` is a Composite MIME body which is defined in [`RFC2046`]: \ /// In the case of multipart entities, in which one or more different @@ -346,18 +345,16 @@ impl<'a> MimeMultiBuilder<'a> { } /// Sets headers to the Composite MIME body. \ - /// It is recommended to use [`set_content_type`] to set header 'Content-Type' - /// and set boundary simultaneously. + /// It is recommended to use [`set_content_type`] to set header + /// 'Content-Type' and set boundary simultaneously. /// /// [`set_content_type`]: MimeMultiBuilder::set_content_type /// /// # Examples /// /// ``` - /// use ylong_http::{ - /// body::MimeMultiBuilder, - /// headers::Headers, - /// }; + /// use ylong_http::body::MimeMultiBuilder; + /// use ylong_http::headers::Headers; /// /// let multi = MimeMultiBuilder::new() /// .set_headers({ @@ -433,8 +430,8 @@ impl<'a> MimeMultiBuilder<'a> { /// the boundary parameter, which consists of 1 to 70 characters from a /// set of characters known to be very robust through mail gateways, and /// NOT ending with white space. \ - /// It is recommended to use [`set_content_type`] to set header 'Content-Type' - /// and set boundary simultaneously. + /// It is recommended to use [`set_content_type`] to set header + /// 'Content-Type' and set boundary simultaneously. /// /// [`RFC2046`]: https://www.rfc-editor.org/rfc/rfc2046#section-5.1.1 /// [`set_content_type`]: MimeMultiBuilder::set_content_type @@ -460,8 +457,7 @@ impl<'a> MimeMultiBuilder<'a> { /// ``` /// use ylong_http::body::MimeMultiBuilder; /// - /// let mut multi = MimeMultiBuilder::new() - /// .set_content_type(b"multipart/mixed", b"ab".to_vec()); + /// let mut multi = MimeMultiBuilder::new().set_content_type(b"multipart/mixed", b"ab".to_vec()); /// ``` pub fn set_content_type(mut self, content_type: &'a [u8], boundary: Vec) -> Self { self.inner = self.inner.and_then(move |mut inner| { @@ -500,8 +496,7 @@ impl<'a> MimeMultiBuilder<'a> { /// use ylong_http::body::{MimeMulti, MimeMultiBuilder}; /// /// let multi1 = MimeMulti::builder().build().unwrap(); - /// let multi = MimeMultiBuilder::new() - /// .add_multi(multi1); + /// let multi = MimeMultiBuilder::new().add_multi(multi1); /// ``` pub fn add_multi(mut self, multi: MimeMulti<'a>) -> Self { self.inner = self.inner.map(move |mut inner| { @@ -518,8 +513,7 @@ impl<'a> MimeMultiBuilder<'a> { /// use ylong_http::body::{MimeMulti, MimeMultiBuilder, XPart}; /// /// let multi1 = MimeMulti::builder().build().unwrap(); - /// let multi = MimeMultiBuilder::new() - /// .add_xpart(XPart::Multi(multi1)); + /// let multi = MimeMultiBuilder::new().add_xpart(XPart::Multi(multi1)); /// ``` pub fn add_xpart(mut self, xpart: XPart<'a>) -> Self { self.inner = self.inner.map(move |mut inner| { diff --git a/ylong_http/src/body/mime/common/part.rs b/ylong_http/src/body/mime/common/part.rs index 8b85eae..6c5e4df 100644 --- a/ylong_http/src/body/mime/common/part.rs +++ b/ylong_http/src/body/mime/common/part.rs @@ -11,20 +11,20 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::headers::{HeaderName, HeaderValue}; -use crate::AsyncRead; -use crate::{ - body::mime::{MixFrom, CR, LF}, - error::HttpError, - headers::{Header, Headers}, -}; -use core::{convert::TryFrom, mem::take}; +use core::convert::TryFrom; +use core::mem::take; use std::io::Read; -/// `MimePart` is a body part of a Composite MIME body which is defined in [`RFC2046`]: \ -/// The body must then contain one or more body parts, each preceded by a boundary -/// delimiter line, and the last one followed by a closing boundary delimiter line. -/// Each body part then consists of a header area, a blank line, and a body area. \ +use crate::body::mime::{MixFrom, CR, LF}; +use crate::error::HttpError; +use crate::headers::{Header, HeaderName, HeaderValue, Headers}; +use crate::AsyncRead; + +/// `MimePart` is a body part of a Composite MIME body which is defined in +/// [`RFC2046`]: The body must then contain one or more body parts, each +/// preceded by a boundary delimiter line, and the last one followed by a +/// closing boundary delimiter line. Each body part then consists of a header +/// area, a blank line, and a body area. /// /// `MimePart` can be built by [`MimePartBuilder`], then sets headers and body. /// @@ -60,7 +60,8 @@ pub struct MimePart<'a> { // // OCTET := pub(crate) headers: Headers, - pub(crate) body: MixFrom<'a>, // all use for encode; owned use for decode + // all use for encode; owned use for decode + pub(crate) body: MixFrom<'a>, } impl<'a> MimePart<'a> { @@ -203,8 +204,8 @@ impl<'a> MimePart<'a> { } } -/// `MimePartBuilder` can set a body part of a Composite MIME body [`MimePart`]. \ -/// `MimePartBuilder` can set headers and body, then builds a [`MimePart`]. \ +/// `MimePartBuilder` can set a body part of a Composite MIME body [`MimePart`]. +/// `MimePartBuilder` can set headers and body, then builds a [`MimePart`]. /// /// [`MimePart`]: MimePart /// @@ -247,7 +248,8 @@ impl<'a> MimePartBuilder<'a> { /// # Examples /// /// ``` - /// use ylong_http::{body::MimePartBuilder, headers::Headers}; + /// use ylong_http::body::MimePartBuilder; + /// use ylong_http::headers::Headers; /// /// let part = MimePartBuilder::new().set_headers({ /// let mut headers = Headers::new(); @@ -348,7 +350,8 @@ impl<'a> MimePartBuilder<'a> { self } - /// Sets body to the MIME body part, the read content is from a synchronous reader. + /// Sets body to the MIME body part, the read content is from a synchronous + /// reader. /// /// # Examples /// @@ -368,7 +371,8 @@ impl<'a> MimePartBuilder<'a> { self } - /// Sets body to the MIME body part, the read content is from a asynchronous reader. + /// Sets body to the MIME body part, the read content is from a asynchronous + /// reader. pub fn body_from_async_reader(mut self, data: T) -> Self where T: AsyncRead + Send + Sync + Unpin + 'static, @@ -413,10 +417,8 @@ pub(crate) enum PartStatus { #[cfg(test)] mod ut_mime_part { - use crate::{ - body::{MimePart, MimePartBuilder}, - headers::Headers, - }; + use crate::body::{MimePart, MimePartBuilder}; + use crate::headers::Headers; /// UT test cases for `MimePartBuilder::new`. /// diff --git a/ylong_http/src/body/mime/decode/multi.rs b/ylong_http/src/body/mime/decode/multi.rs index 97655d0..4a2a3ca 100644 --- a/ylong_http/src/body/mime/decode/multi.rs +++ b/ylong_http/src/body/mime/decode/multi.rs @@ -11,27 +11,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{ - body::{ - mime::{ - common::{ - get_content_type_boundary, get_crlf_contain, trim_back_lwsp_if_end_with_lf, XPart, - }, - decode::BoundaryTag, - DecodeHeaders, MimeMulti, MimePartDecoder, - }, - TokenStatus, - }, - error::{ErrorKind, HttpError}, - headers::Headers, -}; use core::mem::take; +use crate::body::mime::common::{ + get_content_type_boundary, get_crlf_contain, trim_back_lwsp_if_end_with_lf, XPart, +}; +use crate::body::mime::decode::BoundaryTag; +use crate::body::mime::{DecodeHeaders, MimeMulti, MimePartDecoder}; +use crate::body::TokenStatus; +use crate::error::{ErrorKind, HttpError}; +use crate::headers::Headers; + type ByteVec<'a> = Result, &'a [u8]), &'a [u8]>, HttpError>; // TODO: Increases compatibility for preamble and epilogue. -/// `MimeMultiDecoder` can create a [`MimeMulti`] according to a serialized data. +/// `MimeMultiDecoder` can create a [`MimeMulti`] according to a serialized +/// data. /// /// [`MimeMulti`]: MimeMulti /// @@ -64,8 +60,10 @@ type ByteVec<'a> = Result, &'a [u8]), &'a [u8]>, HttpError> /// ``` #[derive(Debug, Default, PartialEq)] pub struct MimeMultiDecoder { - stages: Vec, // stack of stage - multis: Vec>, // stack of multi + // stack of stage + stages: Vec, + // stack of multi + multis: Vec>, } impl MimeMultiDecoder { @@ -74,7 +72,7 @@ impl MimeMultiDecoder { /// # Examples /// /// ``` - /// use ylong_http:: body::MimeMultiDecoder; + /// use ylong_http::body::MimeMultiDecoder; /// /// let mut decoder = MimeMultiDecoder::new(); /// ``` @@ -141,7 +139,8 @@ impl MimeMultiDecoder { } }?; remains = rest; - // at least has the outermost multi stage, unless is replaced by MultiStage::End, so the last stage can uncheck. + // at least has the outermost multi stage, unless is replaced by + // MultiStage::End, so the last stage can uncheck. if remains.is_empty() && !self.last_stage()?.is_end() { break; } @@ -377,11 +376,15 @@ impl MultiStage { #[derive(Debug, PartialEq)] struct DecodeData { - is_finish_first_boundary: bool, // whether read first boundary completely - is_outermost: bool, // whether is outermost multi + // whether read first boundary completely + is_finish_first_boundary: bool, + // whether is outermost multi + is_outermost: bool, boundary: Vec, - tag: BoundaryTag, // 1 is middle part; 2 is end part - src: Vec, // src which is need to encode + // 1 is middle part; 2 is end part + tag: BoundaryTag, + // src which is need to encode + src: Vec, src_idx: usize, } @@ -693,7 +696,8 @@ mod ut_mime_multi_decoder { /// # Brief /// 1. Creates a `MimeMultiDecoder` by `MimeMultiDecoder::new`. /// 2. Uses `MimeMultiDecoder::decode` to decode `MimeMulti`. - /// 3. The `MimeMulti` is composed of several parts, and the boundary has LWSP chars. + /// 3. The `MimeMulti` is composed of several parts, and the boundary has + /// LWSP chars. /// 4. Creates a `MimeMulti` and sets the same parameters to compare. /// 5. Checks whether the result is correct. #[test] @@ -930,16 +934,24 @@ mod ut_mime_multi_decoder { let buf = b"---\r\nkey1:value1\r\n\r\n1111\r\n---\r\nkey2: value2\r\n\r\n2222\r\n-----\r\nabcd"; let mut decoder = MimeMultiDecoder::new(); - let (elem, rest) = decoder.decode(&buf[..3]).unwrap(); //--- + + //--- + let (elem, rest) = decoder.decode(&buf[..3]).unwrap(); assert!(!elem.is_complete()); assert_eq!(rest, b""); - let (elem, rest) = decoder.decode(&buf[3..16]).unwrap(); //\r\nkey1:value1 + + //\r\nkey1:value1 + let (elem, rest) = decoder.decode(&buf[3..16]).unwrap(); assert!(!elem.is_complete()); assert_eq!(rest, b""); - let (elem, rest) = decoder.decode(&buf[16..31]).unwrap(); //\r\n\r\n1111\r\n---\r\n + + //\r\n\r\n1111\r\n---\r\n + let (elem, rest) = decoder.decode(&buf[16..31]).unwrap(); assert!(!elem.is_complete()); assert_eq!(rest, b""); - let (elem, rest) = decoder.decode(&buf[31..60]).unwrap(); //key2: value2\r\n\r\n2222\r\n-----\r\n + + // key2: value2\r\n\r\n2222\r\n-----\r\n + let (elem, rest) = decoder.decode(&buf[31..60]).unwrap(); assert!(elem.is_complete()); let multi1 = MimeMulti::builder() .set_boundary(b"-".to_vec()) @@ -963,7 +975,9 @@ mod ut_mime_multi_decoder { assert_eq!(multi, multi1); } assert_eq!(rest, b""); - let (_elem, rest) = decoder.decode(&buf[60..]).unwrap(); //abcd + + // abcd + let (_elem, rest) = decoder.decode(&buf[60..]).unwrap(); assert_eq!(rest, b"abcd"); } diff --git a/ylong_http/src/body/mime/decode/part.rs b/ylong_http/src/body/mime/decode/part.rs index 47e0e29..1bdd517 100644 --- a/ylong_http/src/body/mime/decode/part.rs +++ b/ylong_http/src/body/mime/decode/part.rs @@ -11,28 +11,26 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{ - body::{ - mime::{ - common::{get_crlf_contain, trim_back_lwsp_if_end_with_lf, trim_front_lwsp}, - decode::BoundaryTag, - DecodeHeaders, MimePart, PartStatus, - }, - TokenStatus, - }, - error::{ErrorKind, HttpError}, - headers::Headers, -}; use core::mem::take; +use crate::body::mime::common::{get_crlf_contain, trim_back_lwsp_if_end_with_lf, trim_front_lwsp}; +use crate::body::mime::decode::BoundaryTag; +use crate::body::mime::{DecodeHeaders, MimePart, PartStatus}; +use crate::body::TokenStatus; +use crate::error::{ErrorKind, HttpError}; +use crate::headers::Headers; + #[derive(Debug, PartialEq)] pub(crate) struct MimePartDecoder { - stage: PartStatus, // Encode stage now + // Encode stage now + stage: PartStatus, headers_decoder: DecodeHeaders, part: MimePart<'static>, - boundary: Vec, // boundary + // boundary + boundary: Vec, tag: BoundaryTag, - src_idx: usize, // marks last "\n" + // marks last "\n" + src_idx: usize, } impl MimePartDecoder { @@ -84,7 +82,8 @@ impl MimePartDecoder { let rest = match self.stage { PartStatus::Start => self.start_decode(remains), PartStatus::Headers => self.headers_decode(remains), - PartStatus::Crlf => Ok(remains), // not use + // not use + PartStatus::Crlf => Ok(remains), PartStatus::Body => self.body_decode(remains), PartStatus::End => { results = TokenStatus::Complete(take(&mut self.part)); @@ -170,10 +169,8 @@ impl MimePartDecoder { #[cfg(test)] mod ut_mime_part_decoder { - use crate::body::{ - mime::{MimePart, MimePartDecoder}, - TokenStatus, - }; + use crate::body::mime::{MimePart, MimePartDecoder}; + use crate::body::TokenStatus; /// UT test cases for `MimePartDecoder::decode`. /// @@ -337,15 +334,18 @@ mod ut_mime_part_decoder { let buf = b"name1:value1\r\nname2:value2\r\n\r\nabcd\r\n--abc\r\nabcd"; let mut decoder = MimePartDecoder::new(); decoder.set_boundary(b"abc".to_vec()); - let (elem, rest) = decoder.decode(&buf[0..3]).unwrap(); // nam + // nam + let (elem, rest) = decoder.decode(&buf[0..3]).unwrap(); assert!(!elem.is_complete()); assert_eq!(rest, b""); - let (elem, rest) = decoder.decode(&buf[3..30]).unwrap(); // e1:value1\r\nname2:value2\r\n\r\n + // e1:value1\r\nname2:value2\r\n\r\n + let (elem, rest) = decoder.decode(&buf[3..30]).unwrap(); assert!(!elem.is_complete()); assert_eq!(rest, b""); - let (elem, rest) = decoder.decode(&buf[30..]).unwrap(); // abcd\r\n--abc\r\nabcd + // abcd\r\n--abc\r\nabcd + let (elem, rest) = decoder.decode(&buf[30..]).unwrap(); assert!(elem.is_complete()); let part1 = MimePart::builder() .header("name1", "value1") diff --git a/ylong_http/src/body/mime/encode/multi.rs b/ylong_http/src/body/mime/encode/multi.rs index 804b314..0e722af 100644 --- a/ylong_http/src/body/mime/encode/multi.rs +++ b/ylong_http/src/body/mime/encode/multi.rs @@ -11,24 +11,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{ - body::{ - async_impl, - mime::{ - common::{data_copy, SizeResult}, - EncodeHeaders, - }, - sync_impl, MimeMulti, MimePartEncoder, TokenStatus, XPart, - }, - headers::Headers, -}; -use core::{ - pin::Pin, - task::{Context, Poll}, -}; +use core::pin::Pin; +use core::task::{Context, Poll}; use std::collections::VecDeque; -/// `MimeMultiEncoder` can get a [`MimeMulti`] to encode into data that can be transmitted. +use crate::body::mime::common::{data_copy, SizeResult}; +use crate::body::mime::EncodeHeaders; +use crate::body::{async_impl, sync_impl, MimeMulti, MimePartEncoder, TokenStatus, XPart}; +use crate::headers::Headers; + +/// `MimeMultiEncoder` can get a [`MimeMulti`] to encode into data that can be +/// transmitted. /// /// [`MimeMulti`]: MimeMulti /// @@ -91,7 +84,8 @@ use std::collections::VecDeque; /// v_str.extend_from_slice(&buf[..len]); /// } /// assert_eq!(v_size, vec![30, 30, 30, 30, 30, 30, 13]); -/// assert_eq!(v_str, +/// assert_eq!( +/// v_str, /// b"--abcde\r\nkey3:value3\r\n\r\n33333\r\n--abcde\r\n\ /// content-type:multipart/mixed; boundary=abc\r\n\r\n--abc\r\n\ /// key1:value1\r\n\r\n111111\r\n--abc\r\nkey2:value2\r\n\r\n22222\r\n\ @@ -101,7 +95,8 @@ use std::collections::VecDeque; #[derive(Debug)] pub struct MimeMultiEncoder<'a> { stages: VecDeque>, - headers: Option, // default is not part, don't encode headers + // default is not part, don't encode headers + headers: Option, src_idx: usize, src: Vec, } @@ -116,9 +111,7 @@ impl<'a> MimeMultiEncoder<'a> { /// ``` /// use ylong_http::body::{MimeMulti, MimeMultiEncoder}; /// - /// let multi = MimeMulti::builder() - /// .build() - /// .unwrap(); + /// let multi = MimeMulti::builder().build().unwrap(); /// let multi_encoder = MimeMultiEncoder::from_multi(multi); /// ``` pub fn from_multi(multi: MimeMulti<'a>) -> Self { @@ -360,11 +353,16 @@ impl async_impl::Body for MimeMultiEncoder<'_> { #[derive(Debug)] enum MultiStage<'a> { - Crlf, // \r\n - Dash, // -- - Boundary(Vec), // boundary - Headers(EncodeHeaders), // headers - MimePart(MimePartEncoder<'a>), // part + // \r\n + Crlf, + // -- + Dash, + // boundary + Boundary(Vec), + // headers + Headers(EncodeHeaders), + // part + MimePart(MimePartEncoder<'a>), } #[cfg(test)] @@ -440,7 +438,8 @@ mod ut_mime_multi_encoder { /// 1. Creates a `MimeMulti`. /// 2. Creates several `MimePart`, sets headers, sets body, builds. /// 3. Adds `MimePart` to `MimeMulti` by `add_part`. - /// 4. Builds a `MimeMultiEncoder` by `from_multi` and encodes synchronously. + /// 4. Builds a `MimeMultiEncoder` by `from_multi` and encodes + /// synchronously. /// 5. Checks whether the result is correct. #[test] fn ut_mime_multi_encoder_data_many_parts() { @@ -477,7 +476,8 @@ mod ut_mime_multi_encoder { /// 1. Creates a `MimeMulti`. /// 2. Creates several `MimePart`, sets headers, sets body, builds. /// 3. Creates a main `MimeMulti`, adds parts. - /// 4. Builds a `MimeMultiEncoder` by `from_multi` and encodes synchronously. + /// 4. Builds a `MimeMultiEncoder` by `from_multi` and encodes + /// synchronously. /// 5. Checks whether the result is correct. #[test] fn ut_mime_multi_encoder_data_many_parts_nesting() { @@ -539,7 +539,8 @@ mod ut_mime_multi_encoder { /// 1. Creates a `MimeMulti`. /// 2. Creates several `MimePart`, sets headers, sets body, builds. /// 3. Creates a main `MimeMulti`, adds parts. - /// 4. Builds a `MimeMultiEncoder` by `from_multi` and encodes asynchronously. + /// 4. Builds a `MimeMultiEncoder` by `from_multi` and encodes + /// asynchronously. /// 5. Checks whether the result is correct. #[cfg(feature = "tokio_base")] #[tokio::test] diff --git a/ylong_http/src/body/mime/encode/part.rs b/ylong_http/src/body/mime/encode/part.rs index 5850dbb..43b3376 100644 --- a/ylong_http/src/body/mime/encode/part.rs +++ b/ylong_http/src/body/mime/encode/part.rs @@ -11,26 +11,19 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{ - body::{ - async_impl, - mime::{ - common::{data_copy, SizeResult, TokenStatus}, - EncodeHeaders, MixFrom, PartStatus, - }, - sync_impl, MimePart, - }, - error::{ErrorKind, HttpError}, -}; -use crate::{AsyncRead, ReadBuf}; -use core::{ - convert::TryFrom, - pin::Pin, - task::{Context, Poll}, -}; +use core::convert::TryFrom; +use core::pin::Pin; +use core::task::{Context, Poll}; use std::io::Read; -/// `MimePartEncoder` can get a [`MimePart`] to encode into data that can be transmitted. +use crate::body::mime::common::{data_copy, SizeResult, TokenStatus}; +use crate::body::mime::{EncodeHeaders, MixFrom, PartStatus}; +use crate::body::{async_impl, sync_impl, MimePart}; +use crate::error::{ErrorKind, HttpError}; +use crate::{AsyncRead, ReadBuf}; + +/// `MimePartEncoder` can get a [`MimePart`] to encode into data that can be +/// transmitted. /// /// [`MimePart`]: MimePart /// @@ -63,11 +56,14 @@ use std::io::Read; /// ``` #[derive(Debug)] pub struct MimePartEncoder<'a> { - stage: PartStatus, // Encode stage now + // Encode stage now + stage: PartStatus, headers_encode: EncodeHeaders, body: Option>, - src: Vec, // src which is need to encode - src_idx: usize, // index of src + // src which is need to encode + src: Vec, + // index of src + src_idx: usize, } impl<'a> MimePartEncoder<'a> { @@ -80,9 +76,7 @@ impl<'a> MimePartEncoder<'a> { /// ``` /// use ylong_http::body::{MimePart, MimePartEncoder}; /// - /// let part = MimePart::builder() - /// .build() - /// .unwrap(); + /// let part = MimePart::builder().build().unwrap(); /// let part_encoder = MimePartEncoder::from_part(part); /// ``` pub fn from_part(part: MimePart<'a>) -> Self { @@ -108,7 +102,8 @@ impl<'a> MimePartEncoder<'a> { PartStatus::Headers => { self.stage = PartStatus::Crlf; if self.body.is_some() { - self.src = b"\r\n".to_vec(); // has body, so has Crlf + // has body, so has Crlf + self.src = b"\r\n".to_vec(); } else { self.src = vec![]; } @@ -116,7 +111,8 @@ impl<'a> MimePartEncoder<'a> { } PartStatus::Crlf => { self.stage = PartStatus::Body; - self.src_idx = 0; // Just record index + // Just record index + self.src_idx = 0; } PartStatus::Body => { self.stage = PartStatus::End; @@ -232,10 +228,8 @@ impl async_impl::Body for MimePartEncoder<'_> { #[cfg(test)] mod ut_mime_part_encoder { - use crate::{ - body::{async_impl, sync_impl, MimePart, MimePartEncoder}, - headers::Headers, - }; + use crate::body::{async_impl, sync_impl, MimePart, MimePartEncoder}; + use crate::headers::Headers; /// UT test cases for `syn::Body::data` of `MimePartEncoder`. /// diff --git a/ylong_http/src/body/mime/mime_test_macro.rs b/ylong_http/src/body/mime/mime_test_macro.rs index fded65a..fd54a81 100644 --- a/ylong_http/src/body/mime/mime_test_macro.rs +++ b/ylong_http/src/body/mime/mime_test_macro.rs @@ -62,8 +62,9 @@ macro_rules! part_encode_compare { }, ); + // default 1 #[allow(unused_assignments, unused_mut)] - let mut len = 1; // default 1 + let mut len = 1; $(len = $size;)? let mut buf = vec![0u8; len]; @@ -107,9 +108,9 @@ macro_rules! part_encode_compare { $(BodyAsyncReader: $body4,)? }, ); - + // default 1 #[allow(unused_assignments, unused_mut)] - let mut len = 1; // default 1 + let mut len = 1; $(len = $size;)? let mut buf = vec![0u8; len]; diff --git a/ylong_http/src/body/mime/mimetype.rs b/ylong_http/src/body/mime/mimetype.rs index bc82690..0dfc983 100644 --- a/ylong_http/src/body/mime/mimetype.rs +++ b/ylong_http/src/body/mime/mimetype.rs @@ -11,10 +11,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::error::{ErrorKind, HttpError}; use core::str; use std::path::Path; +use crate::error::{ErrorKind, HttpError}; + /// A type that defines the general structure of the `MIME` media typing system. /// /// A `MIME` type most-commonly consists of just two parts: @@ -22,12 +23,12 @@ use std::path::Path; /// - `Type` /// - `Subtype` /// -/// `Type` and `SubType` are separated by a slash (/) — with no whitespace between: +/// `Type` and `SubType` are separated by a slash (/) — with no whitespace +/// between: /// /// ```type/subtype``` -/// +/// /// It is case-insensitive but are traditionally written in lowercase, such as: -/// /// ```application/octet-stream```. /// /// # Examples @@ -42,7 +43,8 @@ use std::path::Path; pub struct MimeType<'a> { tag: MimeTypeTag, bytes: &'a [u8], - slash: usize, // Index of '/'. + // Index of '/'. + slash: usize, } impl<'a> MimeType<'a> { @@ -85,6 +87,7 @@ impl<'a> MimeType<'a> { /// /// ``` /// use std::path::Path; + /// /// use ylong_http::body::MimeType; /// /// let path = Path::new("./foo/bar.pdf"); @@ -398,7 +401,8 @@ mime!( "wps", "application/vnd.ms-works", 11, MimeTypeTag::Application; "hlp", "application/winhlp", 11, MimeTypeTag::Application; "bcpio", "application/x-bcpio", 11, MimeTypeTag::Application; - "cdf", "application/x-cdf", 11, MimeTypeTag::Application; // "cdf" also can be "application/x-netcdf" + // "cdf" also can be "application/x-netcdf" + "cdf", "application/x-cdf", 11, MimeTypeTag::Application; "z", "application/x-compress", 11, MimeTypeTag::Application; "tgz", "application/x-compressed", 11, MimeTypeTag::Application; "cpio", "application/x-cpio", 11, MimeTypeTag::Application; @@ -555,7 +559,8 @@ enum MimeTypeTag { Multipart, Text, Video, - Xnew, // A type not included in the standard, beginning with `x-` + // A type not included in the standard, beginning with `x-` + Xnew, } impl MimeTypeTag { @@ -772,9 +777,10 @@ mod ut_mime { /// 2. Checks if the test results are correct. #[test] fn ut_mime_type_from_path() { - use crate::error::HttpError; use std::path::Path; + use crate::error::HttpError; + assert_eq!( MimeType::from_path(Path::new("./foo/bar.evy")), MimeType::from_bytes(b"application/envoy") diff --git a/ylong_http/src/body/mime/mod.rs b/ylong_http/src/body/mime/mod.rs index a445514..ea6d7c8 100644 --- a/ylong_http/src/body/mime/mod.rs +++ b/ylong_http/src/body/mime/mod.rs @@ -21,27 +21,25 @@ mod decode; mod encode; mod mimetype; -pub use common::{MimeMulti, MimeMultiBuilder, MimePart, MimePartBuilder, TokenStatus, XPart}; -pub use decode::MimeMultiDecoder; -pub use encode::MimeMultiEncoder; -pub use encode::MimePartEncoder; -pub use mimetype::MimeType; +use std::io::Cursor; +use std::pin::Pin; +use std::task::{Context, Poll}; +use std::vec::IntoIter; pub(crate) use common::{ DecodeHeaders, EncodeHeaders, HeaderStatus, MixFrom, PartStatus, CR, CRLF, HTAB, LF, SP, }; +pub use common::{MimeMulti, MimeMultiBuilder, MimePart, MimePartBuilder, TokenStatus, XPart}; +pub use decode::MimeMultiDecoder; pub(crate) use decode::MimePartDecoder; +pub use encode::{MimeMultiEncoder, MimePartEncoder}; +pub use mimetype::MimeType; // TODO: reuse mime later. // TODO: Adapter, remove this later. use crate::body::async_impl::{poll_read, Body}; - use crate::{AsyncRead, ReadBuf}; -use std::io::Cursor; -use std::pin::Pin; -use std::task::{Context, Poll}; -use std::vec::IntoIter; /// A structure that helps you build a `multipart/form-data` message. /// @@ -85,8 +83,7 @@ impl MultiPart { /// ``` /// # use ylong_http::body::{MultiPart, Part}; /// - /// let multipart = MultiPart::new() - /// .part(Part::new().name("name").body("xiaoming")); + /// let multipart = MultiPart::new().part(Part::new().name("name").body("xiaoming")); /// ``` pub fn part(mut self, part: Part) -> Self { self.parts.push(part); @@ -115,8 +112,7 @@ impl MultiPart { /// ``` /// # use ylong_http::body::{MultiPart, Part}; /// - /// let multipart = MultiPart::new() - /// .part(Part::new().name("name").body("xiaoming")); + /// let multipart = MultiPart::new().part(Part::new().name("name").body("xiaoming")); /// /// let bytes = multipart.total_bytes(); /// ``` @@ -571,10 +567,8 @@ fn xor_shift() -> u64 { #[cfg(test)] mod ut_mime { - use crate::body::{ - mime::{gen_boundary, MultiPartState, ReadStatus}, - MultiPart, Part, - }; + use crate::body::mime::{gen_boundary, MultiPartState, ReadStatus}; + use crate::body::{MultiPart, Part}; /// UT test cases for `gen_boundar`. /// @@ -620,7 +614,8 @@ mod ut_mime { assert!(part.body.is_none()); } - /// UT test cases for `Part::name`, `Part::name`, `Part::file_name` and `Part::body`. + /// UT test cases for `Part::name`, `Part::name`, `Part::file_name` and + /// `Part::body`. /// /// # Brief /// 1. Creates a `Part` and sets values. diff --git a/ylong_http/src/body/mod.rs b/ylong_http/src/body/mod.rs index 7cb1b32..0bc031b 100644 --- a/ylong_http/src/body/mod.rs +++ b/ylong_http/src/body/mod.rs @@ -38,7 +38,6 @@ //! //! [`EmptyBody`]: EmptyBody //! [`TextBody`]: TextBody -//! // TODO: Support `Trailers`. @@ -57,10 +56,11 @@ pub use text::{Text, TextBody, TextBodyDecoder}; /// Synchronous `Body` trait definition. pub mod sync_impl { - use crate::headers::Headers; use std::error::Error; use std::io::Read; + use crate::headers::Headers; + /// The `sync_impl::Body` trait allows for reading body data synchronously. /// /// # Examples @@ -171,14 +171,16 @@ pub mod sync_impl { /// Asynchronous `Body` trait definition. pub mod async_impl { - use crate::headers::Headers; - use crate::{AsyncRead, ReadBuf}; use core::future::Future; use core::pin::Pin; use core::task::{Context, Poll}; use std::error::Error; - /// The `async_impl::Body` trait allows for reading body data asynchronously. + use crate::headers::Headers; + use crate::{AsyncRead, ReadBuf}; + + /// The `async_impl::Body` trait allows for reading body data + /// asynchronously. /// /// # Examples /// @@ -381,35 +383,15 @@ pub mod async_impl { } } - // TODO: The following code will be useful in the future. - // impl Body for T { - // type Error = std::io::Error; - // - // fn poll_data( - // self: Pin<&mut Self>, - // cx: &mut Context<'_>, - // buf: &mut [u8], - // ) -> Poll> { - // let mut read_buf = ReadBuf::new(buf); - // let filled = read_buf.filled().len(); - // match self.poll_read(cx, &mut read_buf) { - // Poll::Ready(Ok(())) => { - // let new_filled = read_buf.filled().len(); - // Poll::Ready(Ok(new_filled - filled)) - // } - // Poll::Ready(Err(e)) => Poll::Ready(Err(e)), - // Poll::Pending => Poll::Pending, - // } - // } - // } } // Type definitions of the origin of the body data. pub(crate) mod origin { - use crate::AsyncRead; use core::ops::{Deref, DerefMut}; use std::io::Read; + use crate::AsyncRead; + /// A type that represents the body data is from memory. pub struct FromBytes<'a> { pub(crate) bytes: &'a [u8], @@ -536,7 +518,8 @@ mod ut_mod { /// # Brief /// 1. Creates a `async_impl::Body` object. /// 2. Gets its mutable reference. - /// 3. Calls its `async_impl::Body::data` method and then checks the results. + /// 3. Calls its `async_impl::Body::data` method and then checks the + /// results. #[cfg(feature = "tokio_base")] #[tokio::test] async fn ut_asyn_body_mut_asyn_body_data() { diff --git a/ylong_http/src/body/text.rs b/ylong_http/src/body/text.rs index 4013ff0..d39519e 100644 --- a/ylong_http/src/body/text.rs +++ b/ylong_http/src/body/text.rs @@ -11,15 +11,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::origin::{FromAsyncReader, FromBytes, FromReader}; -use super::{async_impl, sync_impl}; -use crate::body::origin::FromAsyncBody; -use crate::{AsyncRead, ReadBuf}; use core::cmp::min; use core::pin::Pin; use core::task::{Context, Poll}; use std::io::{Error, Read}; +use super::origin::{FromAsyncReader, FromBytes, FromReader}; +use super::{async_impl, sync_impl}; +use crate::body::origin::FromAsyncBody; +use crate::{AsyncRead, ReadBuf}; + /// `TextBody` is used to represent the body of plain text type. /// /// You can create a `TextBody` in a variety of ways, such as reading from @@ -38,7 +39,8 @@ use std::io::{Error, Read}; /// let body = TextBody::from_bytes(text.as_bytes()); /// ``` /// -/// This type of `TextBody` implements both [`sync_impl::Body`] and [`async_impl::Body`]. +/// This type of `TextBody` implements both [`sync_impl::Body`] and +/// [`async_impl::Body`]. /// /// # Read From Reader /// @@ -76,8 +78,9 @@ use std::io::{Error, Read}; /// /// # Read Body Content /// -/// After you have created a `TextBody`, you can use the methods of [`sync_impl::Body`] -/// or [`async_impl::Body`] to read data, like the examples below: +/// After you have created a `TextBody`, you can use the methods of +/// [`sync_impl::Body`] or [`async_impl::Body`] to read data, like the examples +/// below: /// /// sync: /// @@ -386,7 +389,8 @@ impl TextBodyDecoder { } /// Decode result of a text buffer. -/// The `state` records the decode status, and the data records the decoded data. +/// The `state` records the decode status, and the data records the decoded +/// data. #[derive(Debug)] pub struct Text<'a> { state: TextState, @@ -394,7 +398,8 @@ pub struct Text<'a> { } impl<'a> Text<'a> { - /// Checks whether this `Text` contains the last valid part of the body data. + /// Checks whether this `Text` contains the last valid part of the body + /// data. /// /// # Examples /// @@ -539,7 +544,8 @@ mod ut_text { /// /// # Brief /// 1. Creates a `TextBody>`. - /// 2. Calls its `async_impl::Body::data` method and then checks the results. + /// 2. Calls its `async_impl::Body::data` method and then checks the + /// results. #[cfg(feature = "tokio_base")] #[tokio::test] async fn ut_text_body_from_bytes_asyn_data() { @@ -588,11 +594,13 @@ mod ut_text { assert_eq!(&buf[..size], b"d!"); } - /// UT test cases for `async_impl::Body::data` of `TextBody>`. + /// UT test cases for `async_impl::Body::data` of + /// `TextBody>`. /// /// # Brief /// 1. Creates a `TextBody>`. - /// 2. Calls its `async_impl::Body::data` method and then checks the results. + /// 2. Calls its `async_impl::Body::data` method and then checks the + /// results. #[cfg(feature = "tokio_base")] #[tokio::test] async fn ut_text_body_from_async_reader_asyn_data() { diff --git a/ylong_http/src/error.rs b/ylong_http/src/error.rs index ca35499..1574e69 100644 --- a/ylong_http/src/error.rs +++ b/ylong_http/src/error.rs @@ -15,20 +15,20 @@ //! //! This module provide unified encapsulation of HTTP errors. //! -//! [`HttpError`] encapsulates error information related to all http protocols including `UriError`, `H1Error`, etc. +//! [`HttpError`] encapsulates error information related to all http protocols +//! including `UriError`, `H1Error`, etc. //! //! [`HttpError`]: HttpError -use crate::request::uri::InvalidUri; use core::fmt::{Debug, Display, Formatter}; use std::convert::Infallible; use std::error::Error; #[cfg(feature = "http1_1")] use crate::h1::H1Error; - #[cfg(feature = "http2")] use crate::h2::H2Error; +use crate::request::uri::InvalidUri; /// Errors that may occur when using this crate. #[derive(Debug, Eq, PartialEq)] diff --git a/ylong_http/src/h1/mod.rs b/ylong_http/src/h1/mod.rs index 1f1c64f..2d8ad9a 100644 --- a/ylong_http/src/h1/mod.rs +++ b/ylong_http/src/h1/mod.rs @@ -18,6 +18,5 @@ mod request; pub(crate) mod response; pub(crate) use error::H1Error; - pub use request::RequestEncoder; pub use response::ResponseDecoder; diff --git a/ylong_http/src/h1/request/encoder.rs b/ylong_http/src/h1/request/encoder.rs index 4512251..637186f 100644 --- a/ylong_http/src/h1/request/encoder.rs +++ b/ylong_http/src/h1/request/encoder.rs @@ -26,7 +26,7 @@ //! .method("GET") //! .url("www.example.com") //! .version("HTTP/1.1") -//! .header("ACCEPT","text/html") +//! .header("ACCEPT", "text/html") //! .body(()) //! .unwrap(); //! @@ -59,13 +59,14 @@ //! assert_eq!(message.as_slice(), result.as_bytes()); //! ``` +use std::io::Read; + use crate::error::{ErrorKind, HttpError}; use crate::headers::{HeaderName, Headers, HeadersIntoIter}; use crate::request::method::Method; use crate::request::uri::Uri; use crate::request::RequestPart; use crate::version::Version; -use std::io::Read; /// A encoder that is used to encode request message in `HTTP/1.1` format. /// @@ -82,7 +83,7 @@ use std::io::Read; /// .method("GET") /// .url("www.example.com") /// .version("HTTP/1.1") -/// .header("ACCEPT","text/html") +/// .header("ACCEPT", "text/html") /// .body(()) /// .unwrap(); /// @@ -128,21 +129,32 @@ pub struct RequestEncoder { } enum EncodeState { - Method, // "Method" phase of encoding request-message. - MethodSp, // "MethodSp" phase of encoding whitespace after method. - Uri, // "Uri" phase of encoding request-message. - UriSp, // "UriSp" phase of encoding whitespace after uri. - Version, // "Version" phase of encoding request-message. - VersionCrlf, // "VersionCrlf" phase of encoding whitespace after version. - Header, // "Header" phase of encoding request-message. - HeaderCrlf, // "HeaderCrlf" phase of encoding /r/n after header. - EncodeFinished, // "EncodeFinished" phase of finishing the encoding. + // "Method" phase of encoding request-message. + Method, + // "MethodSp" phase of encoding whitespace after method. + MethodSp, + // "Uri" phase of encoding request-message. + Uri, + // "UriSp" phase of encoding whitespace after uri. + UriSp, + // "Version" phase of encoding request-message. + Version, + // "VersionCrlf" phase of encoding whitespace after version. + VersionCrlf, + // "Header" phase of encoding request-message. + Header, + // "HeaderCrlf" phase of encoding /r/n after header. + HeaderCrlf, + // "EncodeFinished" phase of finishing the encoding. + EncodeFinished, } // Component encoding status. enum TokenStatus { - Complete(T), // The current component is completely encoded. - Partial(E), // The current component is partially encoded. + // The current component is completely encoded. + Complete(T), + // The current component is partially encoded. + Partial(E), } type TokenResult = Result, HttpError>; @@ -160,7 +172,7 @@ impl RequestEncoder { /// .method("GET") /// .url("www.example.com") /// .version("HTTP/1.1") - /// .header("ACCEPT","text/html") + /// .header("ACCEPT", "text/html") /// .body(()) /// .unwrap(); /// @@ -272,7 +284,7 @@ impl RequestEncoder { /// .method("GET") /// .url("www.example.com") /// .version("HTTP/1.1") - /// .header("ACCEPT","text/html") + /// .header("ACCEPT", "text/html") /// .body(()) /// .unwrap(); /// @@ -284,7 +296,10 @@ impl RequestEncoder { /// let mut buf = [0u8; 1024]; /// let size = encoder.encode(&mut buf).unwrap(); /// // If you set the `is_proxy` flag, the uri will be encoded as a relative path. - /// assert_eq!(&buf[..size], b"GET / HTTP/1.1\r\naccept:text/html\r\n\r\n".as_slice()); + /// assert_eq!( + /// &buf[..size], + /// b"GET / HTTP/1.1\r\naccept:text/html\r\n\r\n".as_slice() + /// ); /// ``` pub fn set_proxy(&mut self, is_proxy: bool) { self.is_proxy = is_proxy; @@ -667,7 +682,8 @@ mod ut_request_encoder { /// 1. Creates a `Request` by calling methods of `Request::builder`. /// 2. Gets a request part by calling `Request::into_parts`. /// 3. Creates a `RequestEncoder` by calling `RequestBuilder::new`. - /// 4. Calls `RequestEncoder::encode` method in a loop and collects the results. + /// 4. Calls `RequestEncoder::encode` method in a loop and collects the + /// results. /// 5. Checks if the test result is correct. #[test] fn ut_request_encoder_encode_1() { diff --git a/ylong_http/src/h1/response/decoder.rs b/ylong_http/src/h1/response/decoder.rs index 3e3aa87..461af7e 100644 --- a/ylong_http/src/h1/response/decoder.rs +++ b/ylong_http/src/h1/response/decoder.rs @@ -11,13 +11,14 @@ // See the License for the specific language governing permissions and // limitations under the License. +use core::mem::take; + use crate::error::{ErrorKind, HttpError}; use crate::h1::H1Error; use crate::headers::Headers; use crate::response::status::StatusCode; use crate::response::ResponsePart; use crate::version::Version; -use core::mem::take; /// `HTTP/1.1` response decoder, which support decoding multi-segment byte /// streams into `Response`. @@ -30,11 +31,7 @@ use core::mem::take; /// /// // The complete message is: /// // "HTTP/1.1 304 OK\r\nContent-Length:4\r\n\r\nbody" -/// let strings = [ -/// "HTTP/1.1 304 OK\r\nCon", -/// "tent-Length:", -/// "4\r\n\r\nbody", -/// ]; +/// let strings = ["HTTP/1.1 304 OK\r\nCon", "tent-Length:", "4\r\n\r\nbody"]; /// /// // We need to create a decoder first. /// let mut decoder = ResponseDecoder::new(); @@ -50,26 +47,40 @@ use core::mem::take; /// // Then we can use the decode result. /// assert_eq!(part.version.as_str(), "HTTP/1.1"); /// assert_eq!(part.status.as_u16(), 304); -/// assert_eq!(part.headers.get("content-length").unwrap().to_str().unwrap(), "4"); +/// assert_eq!( +/// part.headers +/// .get("content-length") +/// .unwrap() +/// .to_str() +/// .unwrap(), +/// "4" +/// ); /// assert_eq!(body, b"body"); /// ``` pub struct ResponseDecoder { - stage: ParseStage, // Parsing phase, corresponding to each component of response-message. + // Parsing phase, corresponding to each component of response-message. + stage: ParseStage, version: Option, status_code: Option, headers: Option, - head_key: Vec, // Cache the parsed header key. - rest: Vec, // Cache the response-message component whose current bytes segment is incomplete, - new_line: bool, // The value is true when the last byte of the current byte segment is CR. + // Cache the parsed header key. + head_key: Vec, + // Cache the response-message component whose current bytes segment is incomplete + rest: Vec, + // The value is true when the last byte of the current byte segment is CR. + new_line: bool, } // Component parsing status enum TokenStatus { - Complete(T), // The current component is completely parsed. - Partial(E), // The current component is not completely parsed. + // The current component is completely parsed. + Complete(T), + // The current component is not completely parsed. + Partial(E), } -// ResponseDecoder parsing phase, All components of response-message are as follows: +// ResponseDecoder parsing phase, All components of response-message are as +// follows: // --------------------------------------------------------- // | HTTP-version SP status-code SP [ reason-phrase ]CRLF | // status-line // | *( field-name ":" OWS field-value OWS CRLF ) | // field-line @@ -78,13 +89,20 @@ enum TokenStatus { // --------------------------------------------------------- #[derive(Clone)] enum ParseStage { - Initial, // Decoder initialization phase, The decoder parses the bytes for the first time. - Version, // "HTTP-version" phase of parsing response-message - StatusCode, // "status-code" phase of parsing response-message - Reason, // "reason-phrase" phase of parsing response-message - StatusCrlf, // CRLF after "reason-phrase" of parsing response-message - Header(HeaderStage), // "field-line" phase of parsing response-message - BlankLine, // CRLF after "field-line" of parsing response-message + // Decoder initialization phase, The decoder parses the bytes for the first time. + Initial, + // "HTTP-version" phase of parsing response-message + Version, + // "status-code" phase of parsing response-message + StatusCode, + // "reason-phrase" phase of parsing response-message + Reason, + // CRLF after "reason-phrase" of parsing response-message + StatusCrlf, + // "field-line" phase of parsing response-message + Header(HeaderStage), + // CRLF after "field-line" of parsing response-message + BlankLine, } // Stage of parsing field-line, the filed line component is as follows: @@ -171,17 +189,14 @@ impl ResponseDecoder { /// # Examples /// /// ``` - /// use ylong_http::version::Version; /// use ylong_http::h1::ResponseDecoder; + /// use ylong_http::version::Version; /// - /// let valid = [ - /// "HTTP/1.1", - /// " 304 OK\r\n\r\n", - /// ]; + /// let valid = ["HTTP/1.1", " 304 OK\r\n\r\n"]; /// let mut decoder = ResponseDecoder::new(); /// // Returns `Ok(None)` if decoder needs more bytes to decode. /// assert_eq!(decoder.decode(valid[0].as_bytes()), Ok(None)); - /// //Returns `ResponsePart` and a slice of bytes if decoder has complete decoding. + /// // Returns `ResponsePart` and a slice of bytes if decoder has complete decoding. /// let (part, body) = decoder.decode(valid[1].as_bytes()).unwrap().unwrap(); /// assert_eq!(part.version, Version::HTTP1_1); /// assert_eq!(part.status.as_u16(), 304); @@ -599,7 +614,8 @@ fn header_insert( let key = name.to_lowercase(); let header_name = key.as_str(); let header_value = value.as_str(); - // If the response contains headers with the same name, add them to one `Headers`. + // If the response contains headers with the same name, add them to one + // `Headers`. headers.append(header_name, header_value)?; Ok(Some(headers)) } @@ -811,7 +827,8 @@ mod ut_decoder { /// UT test cases for `ResponseDecoder::decode`. /// /// # Brief - /// Decode a segmented transmission response and test `ParseStage` parsing rules. + /// Decode a segmented transmission response and test `ParseStage` parsing + /// rules. /// 1. Creates a `ResponseDecoder` by calling `ResponseDecoder::new`. /// 2. Decodes response bytes by calling `ResponseDecoder::decode` /// 3. Checks if the test result is correct. diff --git a/ylong_http/src/h2/decoder.rs b/ylong_http/src/h2/decoder.rs index a9e3a26..fdde469 100644 --- a/ylong_http/src/h2/decoder.rs +++ b/ylong_http/src/h2/decoder.rs @@ -11,6 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::ops::{Deref, DerefMut}; + use super::{Frame, H2Error}; use crate::error::ErrorKind::H2; use crate::h2; @@ -22,7 +24,6 @@ use crate::h2::frame::{ }; use crate::h2::{frame, HpackDecoder, Parts, Setting, Settings}; use crate::headers::Headers; -use std::ops::{Deref, DerefMut}; const FRAME_HEADER_LENGTH: usize = 9; const DEFAULT_MAX_FRAME_SIZE: u32 = 2 << 13; @@ -32,7 +33,8 @@ const DEFAULT_MAX_HEADER_LIST_SIZE: usize = 16 << 20; const MAX_INITIAL_WINDOW_SIZE: usize = (1 << 31) - 1; /// A set of consecutive Frames. -/// When Headers Frames or Continuation Frames are not End Headers, they are represented as `FrameKind::Partial`. +/// When Headers Frames or Continuation Frames are not End Headers, they are +/// represented as `FrameKind::Partial`. /// /// - use `Frames` iterator. /// @@ -52,7 +54,7 @@ const MAX_INITIAL_WINDOW_SIZE: usize = (1 << 31) - 1; /// # Examples /// /// ``` -/// use ylong_http::h2::Frames; +/// use ylong_http::h2::Frames; /// /// # fn get_frames_into_iter(frames: Frames) { /// let mut iter = frames.into_iter(); @@ -145,7 +147,8 @@ impl core::iter::IntoIterator for Frames { } } -/// When Headers Frames or Continuation Frames are not End Headers, they are represented as `FrameKind::Partial`. +/// When Headers Frames or Continuation Frames are not End Headers, they are +/// represented as `FrameKind::Partial`. pub enum FrameKind { /// PUSH_PROMISE or HEADRS frame parsing completed. Complete(Frame), @@ -164,7 +167,7 @@ pub enum FrameKind { /// decoder.set_max_header_list_size(30); /// let data_frame_bytes = &[0, 0, 5, 0, 0, 0, 0, 0, 1, b'h', b'e', b'l', b'l', b'o']; /// let decoded_frames = decoder.decode(data_frame_bytes).unwrap(); -/// let frame_kind =decoded_frames.iter().next().unwrap(); +/// let frame_kind = decoded_frames.iter().next().unwrap(); /// ``` pub struct FrameDecoder { buffer: Vec, @@ -176,7 +179,8 @@ pub struct FrameDecoder { // 9-byte header information of the current frame header: FrameHeader, hpack: HpackDecoderLayer, - // The Headers Frame flags information is saved to ensure the continuity between Headers Frames and Continuation Frames. + // The Headers Frame flags information is saved to ensure the continuity between Headers Frames + // and Continuation Frames. continuations: Continuations, } @@ -306,7 +310,8 @@ impl Frames { } impl FrameDecoder { - /// `FrameDecoder` constructor. Three parameters are defined in SETTINGS Frame. + /// `FrameDecoder` constructor. Three parameters are defined in SETTINGS + /// Frame. pub fn new() -> Self { FrameDecoder::default() } @@ -373,7 +378,8 @@ impl FrameDecoder { &mut self, buf: &'a [u8], ) -> Result, H2Error> { - // Frames of other types or streams are not allowed between Headers Frame and Continuation Frame. + // Frames of other types or streams are not allowed between Headers Frame and + // Continuation Frame. if !self.continuations.is_end_headers && (self.header.stream_id != self.continuations.stream_id || self.header.frame_type != 9) @@ -714,7 +720,9 @@ impl FrameDecoder { self.continuations.is_end_headers = false; self.continuations.stream_id = self.header.stream_id; - // TODO Performance optimization, The storage structure Vec is optimized. When a complete field block exists in the buffer, fragments do not need to be copied to the Vec. + // TODO Performance optimization, The storage structure Vec is optimized. When a + // complete field block exists in the buffer, fragments do not need to be copied + // to the Vec. self.hpack .hpack_decode(&buf[fragment_start_index..fragment_end_index])?; Ok(FrameKind::Partial) @@ -1257,7 +1265,8 @@ mod ut_frame_decoder { FrameKind: frames_iter.next().expect("take next frame from iterator failed !"), ); - // continuation is ("content-length", "9"), so it will append to headers' content-length because of repeat. + // continuation is ("content-length", "9"), so it will append to headers' + // content-length because of repeat. check_complete_frame!( @header; FrameKind: frames_iter.next().expect("take next frame from iterator failed !"), @@ -1284,7 +1293,8 @@ mod ut_frame_decoder { /// /// # Brief /// - /// Test the function of inserting HEADERS of other streams between HEADERS and CONTINUATION of the same stream. + /// Test the function of inserting HEADERS of other streams between HEADERS + /// and CONTINUATION of the same stream. /// 1. Creates a `FrameDecoder`. /// 2. Calls its `FrameDecoder::decode` method. /// 3. Checks the results. @@ -1305,7 +1315,8 @@ mod ut_frame_decoder { /// /// # Brief /// - /// Test the function of inserting CONTINUATION of other streams between HEADERS and CONTINUATION of the same stream. + /// Test the function of inserting CONTINUATION of other streams between + /// HEADERS and CONTINUATION of the same stream. /// 1. Creates a `FrameDecoder`. /// 2. Calls its `FrameDecoder::decode` method. /// 3. Checks the results. @@ -1326,7 +1337,8 @@ mod ut_frame_decoder { /// /// # Brief /// - /// Test a complete Request HEADERS Frames with padding and priority, the purpose is to test the method of `FrameFlags`. + /// Test a complete Request HEADERS Frames with padding and priority, the + /// purpose is to test the method of `FrameFlags`. /// /// 1. Creates a `FrameDecoder`. /// 2. Calls its `FrameDecoder::decode` method. @@ -1384,7 +1396,8 @@ mod ut_frame_decoder { } } - // Tests the case where the payload length is not 8, which should return an error. + // Tests the case where the payload length is not 8, which should return an + // error. decoder.header.payload_length = 7; let result = decoder.decode_ping_payload(ping_payload); assert!(matches!( @@ -1405,12 +1418,16 @@ mod ut_frame_decoder { /// /// # Brief /// - /// This test case checks the behavior of the `decode_priority_payload` method in two scenarios. + /// This test case checks the behavior of the `decode_priority_payload` + /// method in two scenarios. /// /// 1. Creates a `FrameDecoder`. - /// 2. Calls its `decode_priority_payload` method with a valid `priority_payload`. - /// 3. Verifies the method correctly decodes the payload and returns the expected values. - /// 4. Sets the `stream_id` in the header to 0 and checks if the method returns an error as expected. + /// 2. Calls its `decode_priority_payload` method with a valid + /// `priority_payload`. + /// 3. Verifies the method correctly decodes the payload and returns the + /// expected values. + /// 4. Sets the `stream_id` in the header to 0 and checks if the method + /// returns an error as expected. #[test] fn ut_decode_priority_payload() { let mut decoder = FrameDecoder::new(); @@ -1449,12 +1466,16 @@ mod ut_frame_decoder { /// /// # Brief /// - /// This test case checks the behavior of the `decode_goaway_payload` method in two scenarios. + /// This test case checks the behavior of the `decode_goaway_payload` method + /// in two scenarios. /// /// 1. Creates a `FrameDecoder`. - /// 2. Calls its `decode_goaway_payload` method with a valid `goaway_payload`. - /// 3. Verifies the method correctly decodes the payload and returns the expected values. - /// 4. Sets the `stream_id` in the header to a non-zero value and checks if the method returns an error as expected. + /// 2. Calls its `decode_goaway_payload` method with a valid + /// `goaway_payload`. + /// 3. Verifies the method correctly decodes the payload and returns the + /// expected values. + /// 4. Sets the `stream_id` in the header to a non-zero value and checks if + /// the method returns an error as expected. #[test] fn ut_decode_goaway_payload() { let mut decoder = FrameDecoder::new(); @@ -1525,7 +1546,8 @@ mod ut_frame_decoder { } } - // Tests the case where the payload length is not 4, which should return an error. + // Tests the case where the payload length is not 4, which should return an + // error. decoder.header.payload_length = 5; let result = decoder.decode_window_update_payload(window_update_payload); assert!(matches!( @@ -1566,7 +1588,8 @@ mod ut_frame_decoder { } } - // Tests the case where the payload length is not 4, which should return an error. + // Tests the case where the payload length is not 4, which should return an + // error. decoder.header.payload_length = 5; let result = decoder.decode_reset_payload(reset_payload); assert!(matches!( @@ -1602,8 +1625,8 @@ mod ut_frame_decoder { stream_id: 0x0, }; - // Mock a settings payload: [0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01] - // Setting 1: Header Table Size, Value: 128 + // Mock a settings payload: [0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x02, + // 0x00, 0x00, 0x00, 0x01] Setting 1: Header Table Size, Value: 128 // Setting 2: Enable Push, Value: 1 let settings_payload = &[ 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, @@ -1625,7 +1648,8 @@ mod ut_frame_decoder { } // Test the case where the settings frame is an acknowledgment. - // For this, we should set the ACK flag (0x1) and the payload length should be 0. + // For this, we should set the ACK flag (0x1) and the payload length should be + // 0. decoder.header = FrameHeader { payload_length: 0, frame_type: 0x4, @@ -1646,7 +1670,8 @@ mod ut_frame_decoder { } } - // Tests the case where the payload length is not a multiple of 6, which should return an error. + // Tests the case where the payload length is not a multiple of 6, which should + // return an error. decoder.header.payload_length = 5; let result = decoder.decode_settings_payload(settings_payload); assert!(matches!( @@ -1696,7 +1721,8 @@ mod ut_frame_decoder { FrameKind::Partial => {} } - // Tests the case where the payload length is less than the promised_stream_id size, which should return an error. + // Tests the case where the payload length is less than the promised_stream_id + // size, which should return an error. decoder.header.payload_length = 3; let result = decoder.decode_push_promise_payload(push_promise_payload); assert!(matches!( @@ -1785,7 +1811,8 @@ mod ut_frame_decoder { Err(H2Error::ConnectionError(ErrorCode::ProtocolError)) )); - // Test the case where the id is for an InitialWindowSize, but the value is too large + // Test the case where the id is for an InitialWindowSize, but the value is too + // large let result = get_setting(4, 2usize.pow(31) as u32); assert!(matches!( result, diff --git a/ylong_http/src/h2/encoder.rs b/ylong_http/src/h2/encoder.rs index 24b68dd..b6fde06 100644 --- a/ylong_http/src/h2/encoder.rs +++ b/ylong_http/src/h2/encoder.rs @@ -14,8 +14,9 @@ use crate::h2::frame::{FrameFlags, FrameType, Payload, Setting}; use crate::h2::{Frame, HpackEncoder}; -// TODO: Classify encoder errors per RFC specifications into categories like stream or connection errors. -// Identify specific error types such as Frame_size_error/Protocol Error. +// TODO: Classify encoder errors per RFC specifications into categories like +// stream or connection errors. Identify specific error types such as +// Frame_size_error/Protocol Error. #[derive(Debug)] pub enum FrameEncoderErr { EncodingData, @@ -28,17 +29,21 @@ pub enum FrameEncoderErr { enum FrameEncoderState { // The initial state for the frame encoder. Idle, - // The initial state for encoding the HEADERS frame, including the frame header and the Field Block Fragment. + // The initial state for encoding the HEADERS frame, including the frame header and the Field + // Block Fragment. EncodingHeadersFrame, - // The state for encoding the payload of the HEADERS frame, including the header block fragment. + // The state for encoding the payload of the HEADERS frame, including the header block + // fragment. EncodingHeadersPayload, // The state for encoding the padding octets for the HEADERS frame, if the PADDED flag is set. EncodingHeadersPadding, // The state for encoding CONTINUATION frames if the header block exceeds the max_frame_size. EncodingContinuationFrames, - // The final state, indicating that the HEADERS frame and any necessary CONTINUATION frames have been fully encoded. + // The final state, indicating that the HEADERS frame and any necessary CONTINUATION frames + // have been fully encoded. HeadersComplete, - // The initial state for encoding the DATA frame, including the frame header and the Pad Length field (if PADDED flag is set). + // The initial state for encoding the DATA frame, including the frame header and the Pad + // Length field (if PADDED flag is set). EncodingDataHeader, // The state for encoding the actual data payload of the DATA frame. EncodingDataPayload, @@ -72,8 +77,9 @@ enum FrameEncoderState { DataComplete, } -/// A structure for encoding frames into bytes, supporting the serialization of HTTP/2 Frames. -/// It maintains the state of the current frame being encoded and also handles the fragmentation of frames. +/// A structure for encoding frames into bytes, supporting the serialization of +/// HTTP/2 Frames. It maintains the state of the current frame being encoded and +/// also handles the fragmentation of frames. pub struct FrameEncoder { current_frame: Option, max_frame_size: usize, @@ -90,7 +96,8 @@ pub struct FrameEncoder { } impl FrameEncoder { - /// Constructs a new `FrameEncoder` with specified maximum frame size and maximum header list size. + /// Constructs a new `FrameEncoder` with specified maximum frame size and + /// maximum header list size. pub fn new(max_frame_size: usize, max_header_list_size: usize) -> Self { FrameEncoder { current_frame: None, @@ -103,17 +110,20 @@ impl FrameEncoder { remaining_payload_bytes: 0, is_end_stream: false, is_end_headers: false, - header_payload_buffer: vec![0; 16383], // Initialized to default max frame size. + // Initialized to default max frame size. + header_payload_buffer: vec![0; 16383], header_payload_index: 0, } } - /// Sets the current frame to be encoded by the `FrameEncoder`. The state of the encoder is updated based on the payload type of the frame. + /// Sets the current frame to be encoded by the `FrameEncoder`. The state of + /// the encoder is updated based on the payload type of the frame. pub fn set_frame(&mut self, frame: Frame) { self.is_end_stream = frame.flags().is_end_stream(); self.is_end_headers = frame.flags().is_end_headers(); self.current_frame = Some(frame); - self.encoded_bytes = 0; // Reset the encoded bytes counter + // Reset the encoded bytes counter + self.encoded_bytes = 0; // Set the initial state based on the frame payload type match &self.current_frame { @@ -121,7 +131,8 @@ impl FrameEncoder { Payload::Headers(headers) => { self.hpack_encoder.set_parts(headers.get_parts()); self.header_payload_index = 0; - // TODO: Handle potential scenario where HPACK encoding may not be able to complete output in one go. + // TODO: Handle potential scenario where HPACK encoding may not be able to + // complete output in one go. let payload_size = self.hpack_encoder.encode(&mut self.header_payload_buffer); self.remaining_header_payload = payload_size; self.state = FrameEncoderState::EncodingHeadersFrame; @@ -141,8 +152,10 @@ impl FrameEncoder { } } - /// Encodes the current frame into the given buffer. The state of the encoder determines which part of the frame is currently being encoded. - /// This function returns the number of bytes written to the buffer or an error if the encoding process fails. + /// Encodes the current frame into the given buffer. The state of the + /// encoder determines which part of the frame is currently being encoded. + /// This function returns the number of bytes written to the buffer or an + /// error if the encoding process fails. pub fn encode(&mut self, buf: &mut [u8]) -> Result { let mut written_bytes = 0; @@ -292,7 +305,8 @@ impl FrameEncoder { Ok(written_bytes) } - /// Updates the provided setting for the current frame if it is a `Settings` frame. + /// Updates the provided setting for the current frame if it is a `Settings` + /// frame. pub fn update_setting(&mut self, setting: Setting) { if let Some(frame) = &mut self.current_frame { if let Payload::Settings(settings) = frame.payload_mut() { @@ -315,7 +329,8 @@ impl FrameEncoder { fn encode_headers_frame(&mut self, buf: &mut [u8]) -> Result { if let Some(frame) = &self.current_frame { if let Payload::Headers(_) = frame.payload() { - let frame_header_size = 9; // HTTP/2 frame header size is 9 bytes. + // HTTP/2 frame header size is 9 bytes. + let frame_header_size = 9; let remaining_header_bytes = if self.encoded_bytes >= frame_header_size { 0 } else { @@ -339,7 +354,8 @@ impl FrameEncoder { 4 => { *item = frame.flags().bits(); } - // The last 4 bytes (6th to 9th) represent the stream identifier in the frame header. + // The last 4 bytes (6th to 9th) represent the stream identifier in the + // frame header. 5..=8 => { let stream_id_byte_index = header_byte_index - 5; *item = (frame.stream_id() >> (24 - (8 * stream_id_byte_index))) as u8; @@ -437,10 +453,12 @@ impl FrameEncoder { let mut new_flags = FrameFlags::empty(); if self.remaining_header_payload <= self.max_frame_size { if self.is_end_headers { - new_flags.set_end_headers(true); // Sets the END_HEADERS flag on the last CONTINUATION frame. + // Sets the END_HEADER flag on the last CONTINUATION frame. + new_flags.set_end_headers(true); } if self.is_end_stream { - new_flags.set_end_stream(true); // Sets the END_STREAM flag. + // Sets the END_STREAM flag. + new_flags.set_end_stream(true); } } buf[4] = new_flags.bits(); @@ -482,7 +500,8 @@ impl FrameEncoder { fn encode_data_header(&mut self, buf: &mut [u8]) -> Result { if let Some(frame) = &self.current_frame { if let Payload::Data(data_frame) = frame.payload() { - let frame_header_size = 9; // HTTP/2 frame header size is 9 bytes. + // HTTP/2 frame header size is 9 bytes. + let frame_header_size = 9; let remaining_header_bytes = if self.encoded_bytes >= frame_header_size { 0 } else { @@ -506,7 +525,8 @@ impl FrameEncoder { 4 => { *item = frame.flags().bits(); } - // The last 4 bytes (6th to 9th) represent the stream identifier in the frame header. + // The last 4 bytes (6th to 9th) represent the stream identifier in the + // frame header. 5..=8 => { let stream_id_byte_index = header_byte_index - 5; *item = (frame.stream_id() >> (24 - (8 * stream_id_byte_index))) as u8; @@ -534,7 +554,8 @@ impl FrameEncoder { fn encode_data_payload(&mut self, buf: &mut [u8]) -> Result { if let Some(frame) = self.current_frame.as_ref() { if let Payload::Data(data_frame) = frame.payload() { - let frame_header_size = 9; // HTTP/2 frame header size is 9 bytes. + // HTTP/2 frame header size is 9 bytes. + let frame_header_size = 9; let encoded_payload_bytes = self.encoded_bytes - frame_header_size; let payload = data_frame.data(); let bytes_to_write = self.encode_slice(buf, payload, encoded_payload_bytes); @@ -572,7 +593,8 @@ impl FrameEncoder { let bytes_to_write = remaining_padding_bytes.min(buf.len()); for item in buf.iter_mut().take(bytes_to_write) { - *item = 0; // Padding bytes are filled with 0. + // Padding bytes are filled with 0. + *item = 0; } self.encoded_bytes += bytes_to_write; @@ -689,7 +711,8 @@ impl FrameEncoder { fn encode_window_update_frame(&mut self, buf: &mut [u8]) -> Result { if let Some(frame) = &self.current_frame { if let Payload::WindowUpdate(_) = frame.payload() { - let frame_header_size = 9; // HTTP/2 frame header size is 9 bytes. + // HTTP/2 frame header size is 9 bytes. + let frame_header_size = 9; let remaining_header_bytes = if self.encoded_bytes >= frame_header_size { 0 } else { @@ -699,12 +722,14 @@ impl FrameEncoder { for (buf_index, item) in buf.iter_mut().enumerate().take(bytes_to_write) { let header_byte_index = self.encoded_bytes + buf_index; match header_byte_index { - // The first 3 bytes represent the payload length in the frame header. For WindowUpdate frame, this is always 4 bytes. + // The first 3 bytes represent the payload length in the frame header. For + // WindowUpdate frame, this is always 4 bytes. 0..=1 => { *item = 0; } 2 => { - *item = 4; // Window Update frame payload size is always 4 bytes. + // Window Update frame payload size is always 4 bytes. + *item = 4; } // The 4th byte represents the frame type in the frame header. 3 => { @@ -714,7 +739,8 @@ impl FrameEncoder { 4 => { *item = frame.flags().bits(); } - // The last 4 bytes (6th to 9th) represent the stream identifier in the frame header. + // The last 4 bytes (6th to 9th) represent the stream identifier in the + // frame header. 5..=8 => { let stream_id_byte_index = header_byte_index - 5; *item = (frame.stream_id() >> (24 - (8 * stream_id_byte_index))) as u8; @@ -727,7 +753,8 @@ impl FrameEncoder { self.encoded_bytes += bytes_to_write; if self.encoded_bytes == frame_header_size { self.state = FrameEncoderState::EncodingWindowUpdatePayload; - self.encoded_bytes = 0; // Resets the encoded_bytes counter here. + // Resets the encoded_bytes counter here. + self.encoded_bytes = 0; } Ok(bytes_to_write) } else { @@ -794,10 +821,12 @@ impl FrameEncoder { 4 => { buf[4] = frame.flags().bits(); } - // The last 4 bytes (6th to 9th) represent the stream identifier in the frame header. - // For SETTINGS frames, this should always be 0. + // The last 4 bytes (6th to 9th) represent the stream identifier in the + // frame header. For SETTINGS frames, this should + // always be 0. 5..=8 => { - buf[buf_index] = 0; // Stream ID should be 0 for SETTINGS frames. + // Stream ID should be 0 for SETTINGS frames. + buf[buf_index] = 0; } _ => { return Err(FrameEncoderErr::InternalError); @@ -871,7 +900,8 @@ impl FrameEncoder { fn encode_priority_frame(&mut self, buf: &mut [u8]) -> Result { if let Some(frame) = &self.current_frame { if let Payload::Priority(_) = frame.payload() { - let frame_header_size = 9; // HTTP/2 frame header size is 9 bytes. + // HTTP/2 frame header size is 9 bytes. + let frame_header_size = 9; let remaining_header_bytes = if self.encoded_bytes >= frame_header_size { 0 } else { @@ -895,7 +925,8 @@ impl FrameEncoder { 4 => { *item = frame.flags().bits(); } - // The last 4 bytes (6th to 9th) represent the stream identifier in the frame header. + // The last 4 bytes (6th to 9th) represent the stream identifier in the + // frame header. 5..=8 => { let stream_id_byte_index = header_byte_index - 5; *item = (frame.stream_id() >> (24 - (8 * stream_id_byte_index))) as u8; @@ -921,7 +952,8 @@ impl FrameEncoder { fn encode_priority_payload(&mut self, buf: &mut [u8]) -> Result { if let Some(frame) = &self.current_frame { if let Payload::Priority(priority) = frame.payload() { - let frame_header_size = 9; // HTTP/2 frame header size is 9 bytes. + // HTTP/2 frame header size is 9 bytes. + let frame_header_size = 9; let remaining_payload_bytes = 5 - (self.encoded_bytes - frame_header_size); let bytes_to_write = remaining_payload_bytes.min(buf.len()); @@ -1060,7 +1092,8 @@ impl FrameEncoder { match header_byte_index { // The first 3 bytes represent the payload length in the frame header. 0..=2 => { - let payload_len = 8; // PING payload is always 8 bytes. + // PING payload is always 8 bytes. + let payload_len = 8; buf[buf_index] = ((payload_len >> (16 - (8 * buf_index))) & 0xFF) as u8; } // The 4th byte represents the frame type in the frame header. @@ -1071,10 +1104,12 @@ impl FrameEncoder { 4 => { buf[4] = frame.flags().bits(); } - // The last 4 bytes (6th to 9th) represent the stream identifier in the frame header. - // For PING frames, this should always be 0. + // The last 4 bytes (6th to 9th) represent the stream identifier in the + // frame header. For PING frames, this should always + // be 0. 5..=8 => { - buf[buf_index] = 0; // Stream ID should be 0 for PING frames. + // Stream ID should be 0 for PING frames. + buf[buf_index] = 0; } _ => { return Err(FrameEncoderErr::InternalError); @@ -1097,7 +1132,8 @@ impl FrameEncoder { fn encode_ping_payload(&mut self, buf: &mut [u8]) -> Result { if let Some(frame) = &self.current_frame { if let Payload::Ping(ping) = frame.payload() { - let payload_size = 8usize; // PING payload is always 8 bytes. + // PING payload is always 8 bytes. + let payload_size = 8usize; let remaining_payload_bytes = payload_size.saturating_sub(self.encoded_bytes.saturating_sub(9usize)); let bytes_to_write = remaining_payload_bytes.min(buf.len()); @@ -1265,9 +1301,11 @@ mod ut_frame_encoder { let third_encoded = encoder.encode(&mut third_buf).unwrap(); assert_eq!(encoder.state, FrameEncoderState::DataComplete); - assert_eq!(first_encoded, 9); // Updated expected value for first_encoded + // Updated expected value for first_encoded + assert_eq!(first_encoded, 9); assert_eq!(second_encoded, 30); - assert_eq!(third_encoded, 6); // Updated expected value for third_encoded + // Updated expected value for third_encoded + assert_eq!(third_encoded, 6); // Validate the encoded settings let mut expected_encoded_settings = vec![0u8; 60]; @@ -1327,25 +1365,33 @@ mod ut_frame_encoder { assert_eq!(first_buf[0], 0); assert_eq!(first_buf[1], 0); - assert_eq!(first_buf[2], 8); // payload length + // payload length + assert_eq!(first_buf[2], 8); assert_eq!(first_buf[3], FrameType::Ping as u8); - assert_eq!(first_buf[4], 0); // flags - assert_eq!(first_buf[5], 0); // stream id - assert_eq!(first_buf[6], 0); // stream id - assert_eq!(first_buf[7], 0); // stream id - assert_eq!(first_buf[8], 0); // stream id + // flags + assert_eq!(first_buf[4], 0); + // stream id + assert_eq!(first_buf[5], 0); + // stream id + assert_eq!(first_buf[6], 0); + // stream id + assert_eq!(first_buf[7], 0); + // stream id + assert_eq!(first_buf[8], 0); for i in 0..8 { assert_eq!(second_buf[i], ping_payload[i]); } } - /// UT test case for FrameEncoder encoding a sequence of frames: Headers, Data, Headers. + /// UT test case for FrameEncoder encoding a sequence of frames: Headers, + /// Data, Headers. /// /// # Brief /// 1. Creates a FrameEncoder. /// 2. Creates multiple frames including Headers and Data frames. - /// 3. Sets each frame for the encoder and encodes them using buffer segments. + /// 3. Sets each frame for the encoder and encodes them using buffer + /// segments. /// 4. Checks whether the encoding results are correct. #[test] fn ut_continue_frame_encoding() { @@ -1418,7 +1464,8 @@ mod ut_frame_encoder { let frame_flags = FrameFlags::empty(); let frame = Frame::new( - 1, // Stream ID can be non-zero for RST_STREAM frames + // Stream ID can be non-zero for RST_STREAM frames + 1, frame_flags, rst_stream_payload, ); @@ -1428,12 +1475,16 @@ mod ut_frame_encoder { let mut buf = vec![0; 50]; let first_encoded = frame_encoder.encode(&mut buf).unwrap(); - assert_eq!(first_encoded, 9 + 4); // 9 bytes for header, 4 bytes for payload + // 9 bytes for header, 4 bytes for payload + assert_eq!(first_encoded, 9 + 4); assert_eq!(buf[0], 0); - assert_eq!(buf[2], 4); // payload length should be 4 for RST_STREAM frames + // payload length should be 4 for RST_STREAM frames + assert_eq!(buf[2], 4); assert_eq!(buf[3], FrameType::RstStream as u8); - assert_eq!(buf[4], 0); // frame flags should be 0 for RST_STREAM frames - assert_eq!(buf[8], 1); // stream ID should be 1 for this test case + // frame flags should be 0 for RST_STREAM frames + assert_eq!(buf[4], 0); + // stream ID should be 1 for this test case + assert_eq!(buf[8], 1); // Check if encoded error code is correct assert_eq!(&buf[9..13], &error_code.to_be_bytes()); @@ -1458,7 +1509,8 @@ mod ut_frame_encoder { let frame_flags = FrameFlags::empty(); let frame = Frame::new( - 0, // Stream ID can be zero for WINDOW_UPDATE frames. + // Stream ID can be zero for WINDOW_UPDATE frames. + 0, frame_flags, window_update_payload, ); @@ -1468,12 +1520,16 @@ mod ut_frame_encoder { let mut buf = vec![0; 50]; let first_encoded = frame_encoder.encode(&mut buf).unwrap(); - assert_eq!(first_encoded, 9 + 4); // 9 bytes for header, 4 bytes for payload. + // 9 bytes for header, 4 bytes for payload. + assert_eq!(first_encoded, 9 + 4); assert_eq!(buf[0], 0); - assert_eq!(buf[2], 4); // Payload length should be 4 for WINDOW_UPDATE frames. + // Payload length should be 4 for WINDOW_UPDATE frames. + assert_eq!(buf[2], 4); assert_eq!(buf[3], FrameType::WindowUpdate as u8); - assert_eq!(buf[4], 0); // Frame flags should be 0 for WINDOW_UPDATE frames. - assert_eq!(buf[8], 0); // Stream ID should be 0 for this test case. + // Frame flags should be 0 for WINDOW_UPDATE frames. + assert_eq!(buf[4], 0); + // Stream ID should be 0 for this test case. + assert_eq!(buf[8], 0); // Checks if encoded window size increment is correct. assert_eq!(&buf[9..13], &window_size_increment.to_be_bytes()); @@ -1492,7 +1548,8 @@ mod ut_frame_encoder { #[test] fn ut_priority_frame_encoding() { let mut encoder = FrameEncoder::new(4096, 4096); - let stream_dependency = 0x7FFFFFFF; // Maximum value for a 31-bit integer + // Maximum value for a 31-bit integer + let stream_dependency = 0x7FFFFFFF; let priority_payload = Priority::new(true, stream_dependency, 15); let priority_frame = @@ -1505,20 +1562,33 @@ mod ut_frame_encoder { let encoded = encoder.encode(&mut buf).unwrap(); assert_eq!(encoded, 14); - assert_eq!(buf[0], 0); // Payload length (most significant byte) - assert_eq!(buf[1], 0); // Payload length (middle byte) - assert_eq!(buf[2], 5); // Payload length (least significant byte) + // Payload length (most significant byte) + assert_eq!(buf[0], 0); + // Payload length (middle byte) + assert_eq!(buf[1], 0); + // Payload length (least significant byte) + assert_eq!(buf[2], 5); + // Frame flags assert_eq!(buf[3], FrameType::Priority as u8); - assert_eq!(buf[4], 0); // Frame flags - assert_eq!(buf[5], 0); // Stream ID (most significant byte) - assert_eq!(buf[6], 0); // Stream ID (middle bytes) - assert_eq!(buf[7], 0); // Stream ID (middle bytes) - assert_eq!(buf[8], 131); // Stream ID (least significant byte) - assert_eq!(buf[9], (0x80 | ((stream_dependency >> 24) & 0x7F)) as u8); // Exclusive flag and most significant byte of stream dependency - assert_eq!(buf[10], ((stream_dependency >> 16) & 0xFF) as u8); // Stream dependency (middle bytes) - assert_eq!(buf[11], ((stream_dependency >> 8) & 0xFF) as u8); // Stream dependency (middle bytes) - assert_eq!(buf[12], (stream_dependency & 0xFF) as u8); // Stream dependency (least significant byte) - assert_eq!(buf[13], 15); // Weight + assert_eq!(buf[4], 0); + // Stream ID (most significant byte) + assert_eq!(buf[5], 0); + // Stream ID (middle bytes) + assert_eq!(buf[6], 0); + // Stream ID (middle bytes) + assert_eq!(buf[7], 0); + // Stream ID (least significant byte) + assert_eq!(buf[8], 131); + // Exclusive flag and most significant byte of stream dependency + assert_eq!(buf[9], (0x80 | ((stream_dependency >> 24) & 0x7F)) as u8); + // Stream dependency (middle bytes) + assert_eq!(buf[10], ((stream_dependency >> 16) & 0xFF) as u8); + // Stream dependency (middle bytes) + assert_eq!(buf[11], ((stream_dependency >> 8) & 0xFF) as u8); + // Stream dependency (least significant byte) + assert_eq!(buf[12], (stream_dependency & 0xFF) as u8); + // Weight + assert_eq!(buf[13], 15); } /// UT test cases for `FrameEncoder` encoding `GOAWAY` frame. @@ -1564,9 +1634,11 @@ mod ut_frame_encoder { expected_encoded_goaway[8..13].copy_from_slice(&debug_data[..]); - assert_eq!(first_buf[0..3], [0u8, 0, 13]); // payload length should be 13 bytes + // payload length should be 13 bytes + assert_eq!(first_buf[0..3], [0u8, 0, 13]); assert_eq!(first_buf[3], FrameType::Goaway as u8); - assert_eq!(first_buf[4], 0); // flags + // flags + assert_eq!(first_buf[4], 0); // Validate the encoded Last-Stream-ID, Error Code, and debug data assert_eq!(second_buf[..], expected_encoded_goaway[..]); diff --git a/ylong_http/src/h2/error.rs b/ylong_http/src/h2/error.rs index 66c83ab..52b39b7 100644 --- a/ylong_http/src/h2/error.rs +++ b/ylong_http/src/h2/error.rs @@ -24,9 +24,10 @@ //! streams or the entire connection and have no defined semantics in the other //! context. -use crate::error::{ErrorKind, HttpError}; use std::convert::{Infallible, TryFrom}; +use crate::error::{ErrorKind, HttpError}; + /// The http2 error handle implementation #[derive(Debug, Eq, PartialEq)] pub enum H2Error { @@ -132,14 +133,17 @@ impl TryFrom for ErrorCode { #[cfg(test)] mod ut_h2_error { - use super::*; use std::convert::TryInto; + use super::*; + /// Unit test cases for `ErrorCode::try_from`. /// /// # Brief - /// 1. Iterates over a range of valid u32 values that represent `ErrorCode`s. - /// 2. Attempts to convert each u32 value into an `ErrorCode` using `try_into`. + /// 1. Iterates over a range of valid u32 values that represent + /// `ErrorCode`s. + /// 2. Attempts to convert each u32 value into an `ErrorCode` using + /// `try_into`. /// 3. Checks that the conversion is successful for each valid `ErrorCode`. /// 4. Also attempts to convert an invalid u32 value into an `ErrorCode`. /// 5. Checks that the conversion fails for the invalid value. diff --git a/ylong_http/src/h2/frame.rs b/ylong_http/src/h2/frame.rs index d530dcd..94acf73 100644 --- a/ylong_http/src/h2/frame.rs +++ b/ylong_http/src/h2/frame.rs @@ -11,13 +11,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::convert::TryFrom; + use crate::error::HttpError; use crate::h2::{ErrorCode, H2Error, Parts, PseudoHeaders}; use crate::headers; -use std::convert::TryFrom; /// Mask for the END_STREAM flag. -/// When set, indicates that the sender will not send further frames for this stream. +/// When set, indicates that the sender will not send further frames for this +/// stream. pub(crate) const END_STREAM_MASK: u8 = 0x01; /// Mask for the RST_STREAM flag. @@ -25,7 +27,8 @@ pub(crate) const END_STREAM_MASK: u8 = 0x01; pub(crate) const RST_STREAM_MASK: u8 = 0x03; /// Mask for the END_HEADERS flag. -/// When set, indicates that this frame contains an entire header block and not a fragment. +/// When set, indicates that this frame contains an entire header block and not +/// a fragment. pub(crate) const END_HEADERS_MASK: u8 = 0x04; /// Mask for the PADDED flag. @@ -33,15 +36,17 @@ pub(crate) const END_HEADERS_MASK: u8 = 0x04; pub(crate) const PADDED_MASK: u8 = 0x08; /// Mask for the HEADERS_PRIORITY flag. -/// When set, indicates that the headers frame also contains the priority information. +/// When set, indicates that the headers frame also contains the priority +/// information. pub(crate) const HEADERS_PRIORITY_MASK: u8 = 0x20; /// Mask for the ACK flag pub(crate) const ACK_MASK: u8 = 0x1; -/// HTTP/2 frame structure, including the stream ID, flags, and payload information. -/// The frame type information is represented by the `Payload` type. -/// This structure represents the fundamental unit of communication in HTTP/2. +/// HTTP/2 frame structure, including the stream ID, flags, and payload +/// information. The frame type information is represented by the `Payload` +/// type. This structure represents the fundamental unit of communication in +/// HTTP/2. #[derive(Clone)] pub struct Frame { id: StreamId, @@ -90,8 +95,9 @@ pub enum Payload { PushPromise(PushPromise), } -/// Enum representing the different settings that can be included in a SETTINGS frame. -/// Each setting has a different role in the HTTP/2 communication process. +/// Enum representing the different settings that can be included in a SETTINGS +/// frame. Each setting has a different role in the HTTP/2 communication +/// process. #[derive(Clone, PartialEq, Eq, Debug)] pub enum Setting { /// SETTINGS_HEADER_TABLE_SIZE @@ -137,14 +143,16 @@ pub struct Priority { } /// The RST_STREAM frame allows for immediate termination of a stream. -/// RST_STREAM is sent to request cancellation of a stream or to indicate an error situation. +/// RST_STREAM is sent to request cancellation of a stream or to indicate an +/// error situation. #[derive(Clone)] pub struct RstStream { error_code: u32, } /// Represents the PING frame payload. -/// The PING frame is a mechanism for measuring a minimal round-trip time from the sender. +/// The PING frame is a mechanism for measuring a minimal round-trip time from +/// the sender. #[derive(Clone)] pub struct Ping { /// The opaque data of PING @@ -152,14 +160,16 @@ pub struct Ping { } /// Represents the SETTINGS frame payload. -/// The SETTINGS frame conveys configuration parameters that affect how endpoints communicate. +/// The SETTINGS frame conveys configuration parameters that affect how +/// endpoints communicate. #[derive(Clone)] pub struct Settings { settings: Vec, } /// Represents the GOAWAY frame payload. -/// The GOAWAY frame is used to initiate shutdown of a connection or to signal serious error conditions. +/// The GOAWAY frame is used to initiate shutdown of a connection or to signal +/// serious error conditions. #[derive(Clone)] pub struct Goaway { error_code: u32, @@ -175,7 +185,8 @@ pub struct WindowUpdate { } /// Represents the PUSH_PROMISE frame payload. -/// The PUSH_PROMISE frame is used to notify the peer endpoint in advance of streams the sender intends to initiate. +/// The PUSH_PROMISE frame is used to notify the peer endpoint in advance of +/// streams the sender intends to initiate. #[derive(Clone)] pub struct PushPromise { promised_stream_id: u32, @@ -193,7 +204,8 @@ impl Frame { self.id } - /// Constructs a new `Frame` with the given `StreamId`, `FrameFlags`, `Payload`. + /// Constructs a new `Frame` with the given `StreamId`, `FrameFlags`, + /// `Payload`. pub fn new(id: StreamId, flags: FrameFlags, payload: Payload) -> Self { Frame { id, flags, payload } } @@ -280,8 +292,8 @@ impl FrameFlags { } impl Payload { - /// Returns a reference to the Headers if the Payload is of the Headers variant. - /// If the Payload is not of the Headers variant, returns None. + /// Returns a reference to the Headers if the Payload is of the Headers + /// variant. If the Payload is not of the Headers variant, returns None. pub(crate) fn as_headers(&self) -> Option<&Headers> { if let Payload::Headers(headers) = self { Some(headers) @@ -290,8 +302,9 @@ impl Payload { } } - /// Returns the type of the frame (`FrameType`) that this payload would be associated with. - /// The returned `FrameType` is determined based on the variant of the Payload. + /// Returns the type of the frame (`FrameType`) that this payload would be + /// associated with. The returned `FrameType` is determined based on the + /// variant of the Payload. pub fn frame_type(&self) -> FrameType { match self { Payload::Headers(_) => FrameType::Headers, @@ -364,7 +377,8 @@ impl Settings { /// Returns the total length of the settings when encoded. pub fn encoded_len(&self) -> usize { let settings_count = self.settings.len(); - let setting_size = 6; // Each setting has a 2-byte ID and a 4-byte value + // Each setting has a 2-byte ID and a 4-byte value + let setting_size = 6; settings_count * setting_size } } @@ -421,10 +435,10 @@ impl SettingsBuilder { /// use ylong_http::h2::SettingsBuilder; /// /// let settings = SettingsBuilder::new() - /// .enable_push(true) - /// .header_table_size(4096) - /// .max_frame_size(2 << 13) - /// .build(); + /// .enable_push(true) + /// .header_table_size(4096) + /// .max_frame_size(2 << 13) + /// .build(); /// ``` pub fn build(self) -> Settings { Settings::new(self.settings) @@ -438,7 +452,8 @@ impl Default for SettingsBuilder { } impl Goaway { - /// Creates a new Goaway instance with the provided error code, last stream ID, and debug data. + /// Creates a new Goaway instance with the provided error code, last stream + /// ID, and debug data. pub fn new(error_code: u32, last_stream_id: StreamId, debug_data: Vec) -> Self { Goaway { error_code, @@ -464,12 +479,14 @@ impl Goaway { /// Returns the total length of the Goaway frame when encoded. pub fn encoded_len(&self) -> usize { - 8 + self.debug_data.len() // 4-byte Last-Stream-ID + 4-byte Error Code + Debug Data length + 8 + self.debug_data.len() // 4-byte Last-Stream-ID + 4-byte Error Code + + // Debug Data length } } impl WindowUpdate { - /// Creates a new WindowUpdate instance with the provided window size increment. + /// Creates a new WindowUpdate instance with the provided window size + /// increment. pub fn new(window_size_increment: u32) -> Self { WindowUpdate { window_size_increment, @@ -488,7 +505,8 @@ impl WindowUpdate { } impl Priority { - /// Creates a new Priority instance with the provided exclusive flag, stream dependency, and weight. + /// Creates a new Priority instance with the provided exclusive flag, stream + /// dependency, and weight. pub fn new(exclusive: bool, stream_dependency: u32, weight: u8) -> Self { Priority { exclusive, @@ -566,8 +584,10 @@ mod ut_frame { /// 1. Creates a `SettingsBuilder`. /// 2. Sets various setting parameters using builder methods. /// 3. Builds a `Settings` object. - /// 4. Gets a reference to the underlying `Vec` from the `Settings` object. - /// 5. Iterates over each setting in the `Vec` and checks whether it matches the expected value. + /// 4. Gets a reference to the underlying `Vec` from the `Settings` + /// object. + /// 5. Iterates over each setting in the `Vec` and checks whether + /// it matches the expected value. #[test] fn ut_settings_builder() { let settings = SettingsBuilder::new() @@ -578,11 +598,16 @@ mod ut_frame { .build(); let mut setting_iter = settings.get_settings().iter(); - assert_eq!(setting_iter.next(), Some(&Setting::HeaderTableSize(4096))); // Check that the first setting is as expected - assert_eq!(setting_iter.next(), Some(&Setting::EnablePush(true))); // Check that the second setting is as expected - assert_eq!(setting_iter.next(), Some(&Setting::MaxFrameSize(16384))); // Check that the third setting is as expected - assert_eq!(setting_iter.next(), Some(&Setting::MaxHeaderListSize(8192))); // Check that the fourth setting is as expected - assert_eq!(setting_iter.next(), None); // Check that there are no more settings + // Check that the first setting is as expected + assert_eq!(setting_iter.next(), Some(&Setting::HeaderTableSize(4096))); + // Check that the second setting is as expected + assert_eq!(setting_iter.next(), Some(&Setting::EnablePush(true))); + // Check that the third setting is as expected + assert_eq!(setting_iter.next(), Some(&Setting::MaxFrameSize(16384))); + // Check that the fourth setting is as expected + assert_eq!(setting_iter.next(), Some(&Setting::MaxHeaderListSize(8192))); + // Check that there are no more settings + assert_eq!(setting_iter.next(), None); } /// UT test cases for `Ping`. @@ -600,7 +625,8 @@ mod ut_frame { /// UT test cases for `Setting`. /// /// # Brief - /// 1. Creates a `Setting` instance for each possible variant with a specific value. + /// 1. Creates a `Setting` instance for each possible variant with a + /// specific value. /// 2. Checks if the identifier of the `Setting` instance is correct. #[test] fn ut_setting() { diff --git a/ylong_http/src/h2/hpack/decoder.rs b/ylong_http/src/h2/hpack/decoder.rs index 4785d5f..8022c9b 100644 --- a/ylong_http/src/h2/hpack/decoder.rs +++ b/ylong_http/src/h2/hpack/decoder.rs @@ -11,13 +11,14 @@ // See the License for the specific language governing permissions and // limitations under the License. +use core::mem::take; + use crate::h2::error::ErrorCode; use crate::h2::hpack::representation::{ Name, ReprDecStateHolder, ReprDecodeState, ReprDecoder, Representation, }; use crate::h2::hpack::table::{DynamicTable, Header, TableSearcher}; use crate::h2::{H2Error, Parts}; -use core::mem::take; // A structure used to store header lines and octets lengths of header lines. struct HeaderLines { @@ -49,7 +50,8 @@ impl HpackDecoder { } } - /// Users can call `decode` multiple times to decode the byte stream in segments. + /// Users can call `decode` multiple times to decode the byte stream in + /// segments. pub(crate) fn decode(&mut self, buf: &[u8]) -> Result<(), H2Error> { // Initialize ReprDecoder. let mut decoder = ReprDecoder::new(buf); @@ -85,7 +87,8 @@ impl HpackDecoder { } } -/// `Updater` is used to update `DynamicTable` `PseudoHeaders` and `HttpHeaderMap`. +/// `Updater` is used to update `DynamicTable` `PseudoHeaders` and +/// `HttpHeaderMap`. struct Updater<'a> { header_list_size: usize, table: &'a mut DynamicTable, diff --git a/ylong_http/src/h2/hpack/integer.rs b/ylong_http/src/h2/hpack/integer.rs index c668a3f..b907f79 100644 --- a/ylong_http/src/h2/hpack/integer.rs +++ b/ylong_http/src/h2/hpack/integer.rs @@ -18,13 +18,14 @@ //! //! # Introduction //! Integers are used to represent name indexes, header field indexes, or -//! string lengths. An integer representation can start anywhere within an octet. -//! To allow for optimized processing, an integer representation always finishes -//! at the end of an octet. +//! string lengths. An integer representation can start anywhere within an +//! octet. To allow for optimized processing, an integer representation always +//! finishes at the end of an octet. + +use core::cmp::Ordering; use crate::h2::error::ErrorCode; use crate::h2::H2Error; -use core::cmp::Ordering; /// `IntegerDecoder` implementation according to `Pseudocode to decode an /// integer I` in `RFC7541 section-5.1`. @@ -157,7 +158,8 @@ mod ut_integer { /// /// # Brief /// 1. Creates an `IntegerDecoder`. - /// 2. Calls `IntegerDecoder::first_byte()` an `IntegerDecoder::next_byte()`, + /// 2. Calls `IntegerDecoder::first_byte()` an + /// `IntegerDecoder::next_byte()`, /// passing in the specified parameters. /// 3. Checks if the test results are correct. #[test] @@ -205,7 +207,8 @@ mod ut_integer { /// /// # Brief /// 1. Creates an `IntegerEncoder`. - /// 2. Calls `IntegerEncoder::first_byte()` and `IntegerEncoder::next_byte()`, + /// 2. Calls `IntegerEncoder::first_byte()` and + /// `IntegerEncoder::next_byte()`, /// passing in the specified parameters. /// 3. Checks if the test results are correct. #[test] diff --git a/ylong_http/src/h2/hpack/mod.rs b/ylong_http/src/h2/hpack/mod.rs index 3ca6975..03f12ed 100644 --- a/ylong_http/src/h2/hpack/mod.rs +++ b/ylong_http/src/h2/hpack/mod.rs @@ -19,7 +19,8 @@ //! # Introduction //! In [HTTP/1.1], header fields are not compressed. As web pages have grown //! to require dozens to hundreds of requests, the redundant header fields in -//! these requests unnecessarily consume bandwidth, measurably increasing latency. +//! these requests unnecessarily consume bandwidth, measurably increasing +//! latency. //! //! [SPDY] initially addressed this redundancy by compressing header fields //! using the [DEFLATE] format, which proved very effective at efficiently @@ -41,7 +42,6 @@ //! [SPDY]: https://datatracker.ietf.org/doc/html/draft-mbelshe-httpbis-spdy-00 //! [DEFLATE]: https://www.rfc-editor.org/rfc/rfc1951.html //! [CRIME (Compression Ratio Info-leak Made Easy)]: https://en.wikipedia.org/w/index.php?title=CRIME&oldid=660948120 -//! mod decoder; mod encoder; diff --git a/ylong_http/src/h2/hpack/representation/decoder.rs b/ylong_http/src/h2/hpack/representation/decoder.rs index bf72314..1ac595f 100644 --- a/ylong_http/src/h2/hpack/representation/decoder.rs +++ b/ylong_http/src/h2/hpack/representation/decoder.rs @@ -11,12 +11,13 @@ // See the License for the specific language governing permissions and // limitations under the License. +use core::cmp::Ordering; + use crate::h2::error::ErrorCode; use crate::h2::hpack::integer::IntegerDecoder; use crate::h2::hpack::representation::{Name, PrefixBit, Representation}; use crate::h2::H2Error; use crate::huffman::HuffmanDecoder; -use core::cmp::Ordering; /// Decoder implementation for decoding representation. Every time users call /// `decode`, the `ReprDecoder` will try to decode a `Repr`. If `buf` has been diff --git a/ylong_http/src/h2/hpack/representation/encoder.rs b/ylong_http/src/h2/hpack/representation/encoder.rs index 54a884d..66234ea 100644 --- a/ylong_http/src/h2/hpack/representation/encoder.rs +++ b/ylong_http/src/h2/hpack/representation/encoder.rs @@ -11,13 +11,14 @@ // See the License for the specific language governing permissions and // limitations under the License. +use core::cmp::Ordering; +use std::collections::hash_map::IntoIter; + use crate::h2::hpack::integer::IntegerEncoder; use crate::h2::hpack::representation::PrefixIndexMask; use crate::h2::hpack::table::{DynamicTable, Header, TableIndex, TableSearcher}; use crate::h2::{Parts, PseudoHeaders}; use crate::headers::HeadersIntoIter; -use core::cmp::Ordering; -use std::collections::hash_map::IntoIter; /// Encoder implementation for decoding representation. The encode interface /// supports segmented writing. @@ -115,7 +116,8 @@ impl<'a> ReprEncoder<'a> { } } -/// `ReprEncStateHolder` is used to save the intermediate results of the `ReprEncoder`. +/// `ReprEncStateHolder` is used to save the intermediate results of the +/// `ReprEncoder`. pub(crate) struct ReprEncStateHolder { iter: Option, state: Option, diff --git a/ylong_http/src/h2/hpack/representation/mod.rs b/ylong_http/src/h2/hpack/representation/mod.rs index 9438ce8..b2881a4 100644 --- a/ylong_http/src/h2/hpack/representation/mod.rs +++ b/ylong_http/src/h2/hpack/representation/mod.rs @@ -17,7 +17,8 @@ //! [HPACK]: https://httpwg.org/specs/rfc7541.html //! //! # Description from RFC7541 -//! An encoded header field can be represented either as an index or as a literal. +//! An encoded header field can be represented either as an index or as a +//! literal. //! //! An [indexed representation] defines a header field as a reference to an //! entry in either the static table or the dynamic table. @@ -67,7 +68,8 @@ pub(crate) use decoder::{ReprDecStateHolder, ReprDecodeState, ReprDecoder}; pub(crate) use encoder::{ReprEncStateHolder, ReprEncodeState, ReprEncoder}; /// Definition and [binary format] of each of the different -/// [header field representations] and the [dynamic table size update] instruction. +/// [header field representations] and the [dynamic table size update] +/// instruction. /// /// [binary format]: https://www.rfc-editor.org/rfc/rfc7541.html#section-6 /// [header field representations]: https://www.rfc-editor.org/rfc/rfc7541.html#section-3.2 @@ -93,9 +95,9 @@ pub(crate) enum Representation { /// ``` Indexed { index: usize }, - /// A [literal header field with incremental indexing representation] results - /// in appending a header field to the decoded header list and inserting it - /// as a new entry into the dynamic table. + /// A [literal header field with incremental indexing representation] + /// results in appending a header field to the decoded header list and + /// inserting it as a new entry into the dynamic table. /// /// A literal header field with incremental indexing representation starts /// with the '01' 2-bit pattern. @@ -170,10 +172,10 @@ pub(crate) enum Representation { /// ``` LiteralWithoutIndexing { name: Name, value: Vec }, - /// A [literal header field never-indexed representation] results in appending - /// a header field to the decoded header list without altering the dynamic - /// table. Intermediaries **MUST** use the same representation for encoding - /// this header field. + /// A [literal header field never-indexed representation] results in + /// appending a header field to the decoded header list without altering + /// the dynamic table. Intermediaries **MUST** use the same + /// representation for encoding this header field. /// /// A literal header field never-indexed representation starts with the /// '0001' 4-bit pattern. @@ -320,7 +322,8 @@ impl PrefixIndexMask { pub(crate) const LITERAL_WITHOUT_INDEXING: Self = Self(0x0f); } -/// Name of `Representation`. It can be represented as string literals or an index. +/// Name of `Representation`. It can be represented as string literals or an +/// index. pub(crate) enum Name { Index(usize), Literal(Vec), diff --git a/ylong_http/src/h2/hpack/table.rs b/ylong_http/src/h2/hpack/table.rs index 87e6018..7774c1d 100644 --- a/ylong_http/src/h2/hpack/table.rs +++ b/ylong_http/src/h2/hpack/table.rs @@ -14,7 +14,8 @@ use std::collections::VecDeque; use std::ops::Add; -/// `TableSearcher` is used to find specified content in static and dynamic tables. +/// `TableSearcher` is used to find specified content in static and dynamic +/// tables. pub(crate) struct TableSearcher<'a> { dynamic: &'a DynamicTable, } @@ -68,9 +69,10 @@ pub(crate) enum TableIndex { /// [HPACK]: https://httpwg.org/specs/rfc7541.html /// /// # Introduction -/// The dynamic table consists of a list of header fields maintained in first-in, -/// first-out order. The first and newest entry in a dynamic table is at the -/// lowest index, and the oldest entry of a dynamic table is at the highest index. +/// The dynamic table consists of a list of header fields maintained in +/// first-in, first-out order. The first and newest entry in a dynamic table is +/// at the lowest index, and the oldest entry of a dynamic table is at the +/// highest index. /// /// The dynamic table is initially empty. Entries are added as each header block /// is decompressed. @@ -409,11 +411,16 @@ pub(crate) enum Header { impl Header { pub(crate) fn len(&self) -> usize { match self { - Header::Authority => 10, // 10 is the length of ":authority". - Header::Method => 7, // 7 is the length of ":method". - Header::Path => 5, // 5 is the length of ":path". - Header::Scheme => 7, // 7 is the length of "scheme". - Header::Status => 7, // 7 is the length of "status". + // 10 is the length of ":authority". + Header::Authority => 10, + // 7 is the length of ":method". + Header::Method => 7, + // 5 is the length of ":path". + Header::Path => 5, + // 7 is the length of "scheme". + Header::Scheme => 7, + // 7 is the length of "status". + Header::Status => 7, Header::Other(s) => s.len(), } } @@ -533,8 +540,10 @@ mod ut_dynamic_table { /// UT test cases for `StaticTable::header_name` and `StaticTable::header`. /// /// # Brief - /// 1. Iterates over a range of indices, testing both `StaticTable::header_name` and `StaticTable::header`. - /// 2. Verifies the presence or absence of header names and headers based on the given index. + /// 1. Iterates over a range of indices, testing both + /// `StaticTable::header_name` and `StaticTable::header`. + /// 2. Verifies the presence or absence of header names and headers based on + /// the given index. #[test] fn ut_static_table() { // Checking header names for indices 1 to 64 diff --git a/ylong_http/src/h2/mod.rs b/ylong_http/src/h2/mod.rs index f46a0c7..9bdadd7 100644 --- a/ylong_http/src/h2/mod.rs +++ b/ylong_http/src/h2/mod.rs @@ -49,7 +49,6 @@ //! [HTTP]: https://www.rfc-editor.org/rfc/rfc9110.html //! [HTTP/1.1]: https://www.rfc-editor.org/rfc/rfc9112.html //! [TCP]: https://www.rfc-editor.org/rfc/rfc793.html -//! mod decoder; mod encoder; diff --git a/ylong_http/src/h2/pseudo.rs b/ylong_http/src/h2/pseudo.rs index 5e87643..2a15d35 100644 --- a/ylong_http/src/h2/pseudo.rs +++ b/ylong_http/src/h2/pseudo.rs @@ -20,11 +20,11 @@ // TODO: 考虑将 PseudoHeaders 拆分成 `RequestPseudo` 和 `ResponsePseudo`. #[derive(Clone, PartialEq, Eq)] pub struct PseudoHeaders { - authority: Option, // Request. - method: Option, // Request. - path: Option, // Request. - scheme: Option, // Request. - status: Option, // Response. + authority: Option, + method: Option, + path: Option, + scheme: Option, + status: Option, } // TODO: 去掉冗余的方法。 @@ -179,7 +179,8 @@ mod ut_pseudo_headers { /// # Brief /// 1. Creates a `PseudoHeaders`. /// 2. Calls `PseudoHeaders::contains_authority` of it. - /// 3. Calls `PseudoHeaders::contains_authority` of it after its `authority` is set. + /// 3. Calls `PseudoHeaders::contains_authority` of it after its `authority` + /// is set. /// 4. Checks the results. #[test] fn ut_pseudo_headers_contains_authority() { @@ -210,7 +211,8 @@ mod ut_pseudo_headers { /// /// # Brief /// 1. Creates a `PseudoHeaders`. - /// 2. Calls `PseudoHeaders::set_authority` of it to set `authority` a value. + /// 2. Calls `PseudoHeaders::set_authority` of it to set `authority` a + /// value. /// 3. Checks the results. #[test] fn ut_pseudo_headers_set_authority() { @@ -229,7 +231,8 @@ mod ut_pseudo_headers { /// # Brief /// 1. Creates a `PseudoHeaders`. /// 2. Calls `PseudoHeaders::take_authority` of it. - /// 3. Calls `PseudoHeaders::take_authority` of it after its `authority` is set. + /// 3. Calls `PseudoHeaders::take_authority` of it after its `authority` is + /// set. /// 4. Checks the results. #[test] fn ut_pseudo_headers_take_authority() { @@ -245,7 +248,8 @@ mod ut_pseudo_headers { /// # Brief /// 1. Creates a `PseudoHeaders`. /// 2. Calls `PseudoHeaders::contains_method` of it. - /// 3. Calls `PseudoHeaders::contains_method` of it after its `method` is set. + /// 3. Calls `PseudoHeaders::contains_method` of it after its `method` is + /// set. /// 4. Checks the results. #[test] fn ut_pseudo_headers_contains_method() { @@ -377,7 +381,8 @@ mod ut_pseudo_headers { /// # Brief /// 1. Creates a `PseudoHeaders`. /// 2. Calls `PseudoHeaders::contains_scheme` of it. - /// 3. Calls `PseudoHeaders::contains_scheme` of it after its `scheme` is set. + /// 3. Calls `PseudoHeaders::contains_scheme` of it after its `scheme` is + /// set. /// 4. Checks the results. #[test] fn ut_pseudo_headers_contains_scheme() { @@ -443,7 +448,8 @@ mod ut_pseudo_headers { /// # Brief /// 1. Creates a `PseudoHeaders`. /// 2. Calls `PseudoHeaders::contains_status` of it. - /// 3. Calls `PseudoHeaders::contains_status` of it after its `status` is set. + /// 3. Calls `PseudoHeaders::contains_status` of it after its `status` is + /// set. /// 4. Checks the results. #[test] fn ut_pseudo_headers_contains_status() { diff --git a/ylong_http/src/headers.rs b/ylong_http/src/headers.rs index 7b7f7ab..ef7ee58 100644 --- a/ylong_http/src/headers.rs +++ b/ylong_http/src/headers.rs @@ -34,16 +34,23 @@ //! headers.insert("Accept", "text/html").unwrap(); //! headers.insert("Content-Length", "3495").unwrap(); //! -//! assert_eq!(headers.get("accept").unwrap().to_str().unwrap(), "text/html"); -//! assert_eq!(headers.get("content-length").unwrap().to_str().unwrap(), "3495"); +//! assert_eq!( +//! headers.get("accept").unwrap().to_str().unwrap(), +//! "text/html" +//! ); +//! assert_eq!( +//! headers.get("content-length").unwrap().to_str().unwrap(), +//! "3495" +//! ); //! ``` -use crate::error::{ErrorKind, HttpError}; use core::convert::TryFrom; use core::{fmt, slice, str}; use std::collections::hash_map::Entry; use std::collections::{hash_map, HashMap}; +use crate::error::{ErrorKind, HttpError}; + /// HTTP `Header`, which consists of [`HeaderName`] and [`HeaderValue`]. /// /// `Header` is called `Field` in RFC9110. HTTP uses fields to provide data in @@ -56,6 +63,7 @@ use std::collections::{hash_map, HashMap}; /// /// ``` /// use core::convert::TryFrom; +/// /// use ylong_http::headers::Header; /// /// // This header name string will be normalized to lowercase. @@ -97,6 +105,7 @@ impl Header { /// /// ``` /// use core::convert::TryFrom; + /// /// use ylong_http::headers::Header; /// /// let header = Header::try_from(("Example-Field", "Foo")).unwrap(); @@ -114,6 +123,7 @@ impl Header { /// /// ``` /// use core::convert::TryFrom; + /// /// use ylong_http::headers::Header; /// /// let header = Header::try_from(("Example-Field", "Foo")).unwrap(); @@ -125,12 +135,14 @@ impl Header { &self.value } - /// Consumes this `Header`, get the underlying `HeaderName` and `HeaderValue`. + /// Consumes this `Header`, get the underlying `HeaderName` and + /// `HeaderValue`. /// /// # Examples /// /// ``` /// use core::convert::TryFrom; + /// /// use ylong_http::headers::Header; /// /// let header = Header::try_from(("Example-Field", "Foo")).unwrap(); @@ -312,7 +324,8 @@ impl HeaderValue { }) } - /// Consume another `HeaderValue`, and then appends it to this `HeaderValue`. + /// Consume another `HeaderValue`, and then appends it to this + /// `HeaderValue`. /// /// # Examples /// @@ -530,7 +543,8 @@ pub type HeaderValueIterMut<'a> = slice::IterMut<'a, Vec>; /// HTTP `Headers`, which is called [`Fields`] in RFC9110. /// -/// Fields are sent and received within the header and trailer sections of messages. +/// Fields are sent and received within the header and trailer sections of +/// messages. /// /// [`Fields`]: https://httpwg.org/specs/rfc9110.html#fields /// @@ -544,8 +558,14 @@ pub type HeaderValueIterMut<'a> = slice::IterMut<'a, Vec>; /// headers.insert("Content-Length", "3495").unwrap(); /// headers.append("Accept", "text/plain").unwrap(); /// -/// assert_eq!(headers.get("accept").unwrap().to_str().unwrap(), "text/html, text/plain"); -/// assert_eq!(headers.get("content-length").unwrap().to_str().unwrap(), "3495"); +/// assert_eq!( +/// headers.get("accept").unwrap().to_str().unwrap(), +/// "text/html, text/plain" +/// ); +/// assert_eq!( +/// headers.get("content-length").unwrap().to_str().unwrap(), +/// "3495" +/// ); /// ``` #[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct Headers { @@ -629,9 +649,9 @@ impl Headers { /// /// ``` /// use ylong_http::headers::Headers; - /// + /// /// let mut headers = Headers::new(); - /// headers.append("accept","text/html").unwrap(); + /// headers.append("accept", "text/html").unwrap(); /// /// let value = headers.get("accept"); /// assert_eq!(value.unwrap().to_str().unwrap(), "text/html"); @@ -677,7 +697,8 @@ impl Headers { /// If the input argument could not be successfully converted to a `Header`, /// `Err` is returned. /// - /// If the `Headers` did not have this `HeaderName` present, `None` is returned. + /// If the `Headers` did not have this `HeaderName` present, `None` is + /// returned. /// /// If the `Headers` did have this `HeaderName` present, the new /// `HeaderValue` is updated, and the old `HeaderValue` is returned. @@ -789,7 +810,7 @@ impl Headers { /// use ylong_http::headers::Headers; /// /// let mut headers = Headers::new(); - /// headers.append("accept","text/html").unwrap(); + /// headers.append("accept", "text/html").unwrap(); /// /// for (_name, _value) in headers.iter() { /// // Operate on each `HeaderName` and `HeaderValue` pair. @@ -808,7 +829,7 @@ impl Headers { /// use ylong_http::headers::Headers; /// /// let mut headers = Headers::new(); - /// headers.append("accept","text/html").unwrap(); + /// headers.append("accept", "text/html").unwrap(); /// /// for (_name, _value) in headers.iter_mut() { /// // Operate on each `HeaderName` and `HeaderValue` pair. @@ -833,7 +854,7 @@ impl IntoIterator for Headers { /// use ylong_http::headers::Headers; /// /// let mut headers = Headers::new(); - /// headers.append("accept","text/html").unwrap(); + /// headers.append("accept", "text/html").unwrap(); /// /// for (_name, _value) in headers.into_iter() { /// // Operate on each `HeaderName` and `HeaderValue` pair. @@ -874,7 +895,7 @@ impl<'a> IntoIterator for &'a mut Headers { /// use ylong_http::headers::Headers; /// /// let mut headers = Headers::new(); -/// headers.append("accept","text/html").unwrap(); +/// headers.append("accept", "text/html").unwrap(); /// /// for (_name, _value) in headers.iter() { /// // Operate on each `HeaderName` and `HeaderValue` pair. @@ -894,7 +915,7 @@ pub type HeadersIter<'a> = hash_map::Iter<'a, HeaderName, HeaderValue>; /// use ylong_http::headers::Headers; /// /// let mut headers = Headers::new(); -/// headers.append("accept","text/html").unwrap(); +/// headers.append("accept", "text/html").unwrap(); /// /// for (_name, _value) in headers.iter_mut() { /// // Operate on each `HeaderName` and `HeaderValue` pair. @@ -914,7 +935,7 @@ pub type HeadersIterMut<'a> = hash_map::IterMut<'a, HeaderName, HeaderValue>; /// use ylong_http::headers::Headers; /// /// let mut headers = Headers::new(); -/// headers.append("accept","text/html").unwrap(); +/// headers.append("accept", "text/html").unwrap(); /// /// for (_name, _value) in headers.into_iter() { /// // Operate on each `HeaderName` and `HeaderValue` pair. @@ -922,7 +943,8 @@ pub type HeadersIterMut<'a> = hash_map::IterMut<'a, HeaderName, HeaderValue>; /// ``` pub type HeadersIntoIter = hash_map::IntoIter; -// HEADER_CHARS is used to check whether char is correct and transfer to lowercase. +// HEADER_CHARS is used to check whether char is correct and transfer to +// lowercase. #[rustfmt::skip] const HEADER_CHARS: [u8; 256] = [ // 0 1 2 3 4 5 6 7 8 9 @@ -956,9 +978,10 @@ const HEADER_CHARS: [u8; 256] = [ #[cfg(test)] mod ut_headers { - use crate::headers::{Header, HeaderName, HeaderValue, Headers}; use std::collections::HashMap; + use crate::headers::{Header, HeaderName, HeaderValue, Headers}; + /// UT test cases for `HeaderName::from_bytes`. /// /// # Brief @@ -1007,7 +1030,8 @@ mod ut_headers { /// /// # Brief /// 1. Creates a `Header`. - /// 2. Calls Header::from_raw_parts, name, value and into_parts respectively. + /// 2. Calls Header::from_raw_parts, name, value and into_parts + /// respectively. /// 3. Checks if the test results are corrent. #[test] fn ut_header_methods() { @@ -1065,7 +1089,8 @@ mod ut_headers { /// /// # Brief /// 1. Creates a `HeaderValue`. - /// 2. Calls `HeaderValue::is_sensitive` to check if the test results are correct. + /// 2. Calls `HeaderValue::is_sensitive` to check if the test results are + /// correct. #[test] fn ut_header_value_is_sensitive() { let mut value = HeaderValue { @@ -1081,7 +1106,8 @@ mod ut_headers { /// /// # Brief /// 1. Creates a `Headers`. - /// 2. Gets the mutable `HeaderValue` by calling `HeaderValue::append_bytes`. + /// 2. Gets the mutable `HeaderValue` by calling + /// `HeaderValue::append_bytes`. /// 3. Modifies `HeaderValue`. /// 3. Checks if the test results are correct. #[test] @@ -1098,7 +1124,8 @@ mod ut_headers { /// /// # Brief /// 1. Creates a `HeaderValue`. - /// 2. Adds new value content into `HeaderValue` by calling `HeaderValue::append_bytes`. + /// 2. Adds new value content into `HeaderValue` by calling + /// `HeaderValue::append_bytes`. /// 3. Checks if the test results are correct. #[test] fn ut_header_value_append_bytes() { diff --git a/ylong_http/src/huffman/mod.rs b/ylong_http/src/huffman/mod.rs index 083565f..faa5d96 100644 --- a/ylong_http/src/huffman/mod.rs +++ b/ylong_http/src/huffman/mod.rs @@ -35,10 +35,10 @@ mod consts; -use consts::{HUFFMAN_DECODE, HUFFMAN_ENCODE}; - use core::cmp::Ordering; +use consts::{HUFFMAN_DECODE, HUFFMAN_ENCODE}; + /// Converts a string to a Huffman code, and then put it into the /// specified `Vec`. pub(crate) fn huffman_encode(src: &[u8], dst: &mut Vec) { @@ -68,7 +68,8 @@ pub(crate) fn huffman_encode(src: &[u8], dst: &mut Vec) { // +--------------------------------+-----------------+ let mut state = 0u64; - // The initial value of `unfilled` is equal to the number of bits in the `state`. + // The initial value of `unfilled` is equal to the number of bits in the + // `state`. let mut unfilled = 64; for byte in src.iter() { @@ -117,8 +118,8 @@ pub(crate) fn huffman_encode(src: &[u8], dst: &mut Vec) { } } -/// Converts a Huffman code into a literal string at one time, and then put it into the -/// specified `Vec`. +/// Converts a Huffman code into a literal string at one time, and then put it +/// into the specified `Vec`. /// /// The algorithm comes from crate [h2]. /// @@ -355,7 +356,8 @@ mod ut_huffman { /// /// # Brief /// 1. Creates a `HuffmanDecoder`. - /// 1. Calls `decode` and `finish` function, passing in the specified parameters. + /// 1. Calls `decode` and `finish` function, passing in the specified + /// parameters. /// 2. Checks if the test results are correct. #[test] fn ut_huffman_decoder() { diff --git a/ylong_http/src/lib.rs b/ylong_http/src/lib.rs index dda5766..9fac33a 100644 --- a/ylong_http/src/lib.rs +++ b/ylong_http/src/lib.rs @@ -19,7 +19,6 @@ //! //! # Support HTTP Version //! - `HTTP1.1` -//! // TODO: Need doc. #[cfg(feature = "http1_1")] @@ -47,6 +46,5 @@ pub(crate) mod test_util; #[cfg(feature = "tokio_base")] pub(crate) use tokio::io::{AsyncRead, AsyncReadExt, ReadBuf}; - #[cfg(feature = "ylong_base")] pub(crate) use ylong_runtime::io::{AsyncRead, AsyncReadExt, ReadBuf}; diff --git a/ylong_http/src/request/method.rs b/ylong_http/src/request/method.rs index db2c9bb..3025b84 100644 --- a/ylong_http/src/request/method.rs +++ b/ylong_http/src/request/method.rs @@ -27,9 +27,10 @@ //! assert_eq!(Method::GET.as_str(), "GET"); //! ``` -use crate::error::{ErrorKind, HttpError}; use core::convert::TryFrom; +use crate::error::{ErrorKind, HttpError}; + /// HTTP `Method` implementation. /// /// # Examples @@ -100,7 +101,8 @@ impl Method { /// [`RFC9110 9.3.8`]: https://httpwg.org/specs/rfc9110.html#TRACE pub const TRACE: Self = Self(Inner::Trace); - /// Tries converting &[u8] to `Method`. Only uppercase letters are supported. + /// Tries converting &[u8] to `Method`. Only uppercase letters are + /// supported. /// /// # Examples /// diff --git a/ylong_http/src/request/mod.rs b/ylong_http/src/request/mod.rs index 96047b3..9d3d84c 100644 --- a/ylong_http/src/request/mod.rs +++ b/ylong_http/src/request/mod.rs @@ -33,8 +33,8 @@ //! .method("GET") //! .url("www.example.com") //! .version("HTTP/1.1") -//! .header("ACCEPT","text/html") -//! .append_header("ACCEPT","application/xml") +//! .header("ACCEPT", "text/html") +//! .append_header("ACCEPT", "application/xml") //! .body(()) //! .unwrap(); //! @@ -50,6 +50,8 @@ pub mod method; pub mod uri; +use core::convert::TryFrom; + use method::Method; use uri::Uri; @@ -57,7 +59,6 @@ use crate::body::MultiPart; use crate::error::{ErrorKind, HttpError}; use crate::headers::{Header, HeaderName, HeaderValue, Headers}; use crate::version::Version; -use core::convert::TryFrom; /// HTTP `Request`. A `Request` consists of a request line and a body. /// @@ -105,7 +106,8 @@ impl Request<()> { RequestBuilder::new().method(Method::GET).url(uri) } - /// Creates a `RequestBuilder` for the given `Uri` with method set to `HEAD`. + /// Creates a `RequestBuilder` for the given `Uri` with method set to + /// `HEAD`. /// /// # Examples /// @@ -122,7 +124,8 @@ impl Request<()> { RequestBuilder::new().method(Method::HEAD).url(uri) } - /// Creates a `RequestBuilder` for the given `Uri` with method set to `POST`. + /// Creates a `RequestBuilder` for the given `Uri` with method set to + /// `POST`. /// /// # Examples /// @@ -156,7 +159,8 @@ impl Request<()> { RequestBuilder::new().method(Method::PUT).url(uri) } - /// Creates a `RequestBuilder` for the given `Uri` with method set to `DELETE`. + /// Creates a `RequestBuilder` for the given `Uri` with method set to + /// `DELETE`. /// /// # Examples /// @@ -173,7 +177,8 @@ impl Request<()> { RequestBuilder::new().method(Method::DELETE).url(uri) } - /// Creates a `RequestBuilder` for the given `Uri` with method set to `CONNECT`. + /// Creates a `RequestBuilder` for the given `Uri` with method set to + /// `CONNECT`. /// /// # Examples /// @@ -190,7 +195,8 @@ impl Request<()> { RequestBuilder::new().method(Method::CONNECT).url(uri) } - /// Creates a `RequestBuilder` for the given `Uri` with method set to `OPTIONS`. + /// Creates a `RequestBuilder` for the given `Uri` with method set to + /// `OPTIONS`. /// /// # Examples /// @@ -207,7 +213,8 @@ impl Request<()> { RequestBuilder::new().method(Method::OPTIONS).url(uri) } - /// Creates a `RequestBuilder` for the given `Uri` with method set to `TRACE`. + /// Creates a `RequestBuilder` for the given `Uri` with method set to + /// `TRACE`. /// /// # Examples /// @@ -459,8 +466,8 @@ impl Clone for Request { /// .method("GET") /// .url("www.example.com") /// .version("HTTP/1.1") -/// .header("ACCEPT","text/html") -/// .append_header("ACCEPT","application/xml") +/// .header("ACCEPT", "text/html") +/// .append_header("ACCEPT", "application/xml") /// .body(()) /// .unwrap(); /// @@ -565,7 +572,7 @@ impl RequestBuilder { /// use ylong_http::headers::Headers; /// use ylong_http::request::RequestBuilder; /// - /// let request = RequestBuilder::new().header("ACCEPT","text/html"); + /// let request = RequestBuilder::new().header("ACCEPT", "text/html"); /// ``` pub fn header(mut self, name: N, value: V) -> Self where @@ -590,7 +597,7 @@ impl RequestBuilder { /// use ylong_http::headers::Headers; /// use ylong_http::request::RequestBuilder; /// - /// let request = RequestBuilder::new().append_header("ACCEPT","text/html"); + /// let request = RequestBuilder::new().append_header("ACCEPT", "text/html"); /// ``` pub fn append_header(mut self, name: N, value: V) -> Self where @@ -674,8 +681,8 @@ impl Default for RequestBuilder { /// `RequestPart`, which is called [`Request Line`] in [`RFC9112`]. /// /// A request-line begins with a method token, followed by a single space (SP), -/// the request-target, and another single space (SP), and ends with the protocol -/// version. +/// the request-target, and another single space (SP), and ends with the +/// protocol version. /// /// [`RFC9112`]: https://httpwg.org/specs/rfc9112.html /// [`Request Line`]: https://httpwg.org/specs/rfc9112.html#request.line @@ -715,10 +722,11 @@ impl Default for RequestPart { #[cfg(test)] mod ut_request { + use core::convert::TryFrom; + use super::{Method, Request, RequestBuilder, RequestPart, Uri}; use crate::headers::Headers; use crate::version::Version; - use core::convert::TryFrom; /// UT test cases for `RequestBuilder::build`. /// diff --git a/ylong_http/src/request/uri.rs b/ylong_http/src/request/uri.rs index 2b63901..359b07d 100644 --- a/ylong_http/src/request/uri.rs +++ b/ylong_http/src/request/uri.rs @@ -18,9 +18,10 @@ //! //! [`URI`]: https://httpwg.org/specs/rfc9110.html#uri.references -use crate::error::{ErrorKind, HttpError}; use core::convert::{Infallible, TryFrom, TryInto}; +use crate::error::{ErrorKind, HttpError}; + // Maximum uri length. const MAX_URI_LEN: usize = (u16::MAX - 1) as usize; @@ -469,12 +470,12 @@ impl UriBuilder { /// use ylong_http::request::uri::UriBuilder; /// /// let uri = UriBuilder::new() - /// .scheme("http") - /// .authority("example.com:80") - /// .path("/foo") - /// .query("a=1") - /// .build() - /// .unwrap(); + /// .scheme("http") + /// .authority("example.com:80") + /// .path("/foo") + /// .query("a=1") + /// .build() + /// .unwrap(); /// ``` pub fn build(self) -> Result { self.unprocessed @@ -946,7 +947,8 @@ fn scheme_token(bytes: &[u8]) -> Result<(Option, &[u8]), InvalidUri> { Some((0, _)) => return Err(InvalidUri::InvalidScheme), _ => return Ok((None, bytes)), }; - // Currently, only HTTP and HTTPS are supported. Therefore, you need to verify the scheme content. + // Currently, only HTTP and HTTPS are supported. Therefore, you need to verify + // the scheme content. if bytes[..pos].eq_ignore_ascii_case(b"http") { Ok((Some(Protocol::Http.into()), &bytes[HTTP_SCHEME_LENGTH..])) } else if bytes[..pos].eq_ignore_ascii_case(b"https") { @@ -985,7 +987,8 @@ fn authority_token(bytes: &[u8]) -> Result<(Option, &[u8]), InvalidUr } } } - // TODO According to RFC3986, the character @ can be one of the reserved characters, which needs to be improved after being familiar with the rules. + // TODO According to RFC3986, the character @ can be one of the reserved characters, + // which needs to be improved after being familiar with the rules. b'@' => { return Err(InvalidUri::UriContainUserinfo); } diff --git a/ylong_http/src/response/mod.rs b/ylong_http/src/response/mod.rs index a093444..1e4bfd8 100644 --- a/ylong_http/src/response/mod.rs +++ b/ylong_http/src/response/mod.rs @@ -23,7 +23,8 @@ use crate::version::Version; /// HTTP `Response` Implementation. /// -/// The status-line and field-line of a response-message are stored in `Response`. +/// The status-line and field-line of a response-message are stored in +/// `Response`. /// /// The body can be saved in the user-defined type. /// @@ -85,8 +86,8 @@ impl Clone for Response { /// `ResponsePart`, which is called [`Status Line`] in [`RFC9112`]. /// /// A request-line begins with a method token, followed by a single space (SP), -/// the request-target, and another single space (SP), and ends with the protocol -/// version. +/// the request-target, and another single space (SP), and ends with the +/// protocol version. /// /// [`RFC9112`]: https://httpwg.org/specs/rfc9112.html /// [`Status Line`]: https://httpwg.org/specs/rfc9112.html#status.line @@ -130,7 +131,8 @@ mod ut_response { /// /// # Brief /// 1. Creates a `ResponsePart` by calling `ResponseDecoder::decode`. - /// 2. Gets the reference of a `StatusCode` by calling `Response::status_code`. + /// 2. Gets the reference of a `StatusCode` by calling + /// `Response::status_code`. /// 3. Checks if the test result is correct. #[test] fn ut_response_status_code() { diff --git a/ylong_http/src/response/status.rs b/ylong_http/src/response/status.rs index 61d8484..d296d26 100644 --- a/ylong_http/src/response/status.rs +++ b/ylong_http/src/response/status.rs @@ -20,10 +20,11 @@ //! //! [`Status Codes`]: https://httpwg.org/specs/rfc9110.html#status.codes -use crate::error::{ErrorKind, HttpError}; use core::convert::TryFrom; use core::fmt::{Display, Formatter}; +use crate::error::{ErrorKind, HttpError}; + /// HTTP [`Status Codes`] implementation. /// /// [`Status Codes`]: https://httpwg.org/specs/rfc9110.html#status.codes diff --git a/ylong_http/src/version.rs b/ylong_http/src/version.rs index 7311dac..f8817d7 100644 --- a/ylong_http/src/version.rs +++ b/ylong_http/src/version.rs @@ -21,9 +21,10 @@ //! //! [`Version`]: https://httpwg.org/specs/rfc9110.html#protocol.version -use crate::error::{ErrorKind, HttpError}; use core::convert::TryFrom; +use crate::error::{ErrorKind, HttpError}; + /// HTTP [`Version`] implementation. /// /// [`Version`]: https://httpwg.org/specs/rfc9110.html#protocol.version @@ -86,9 +87,10 @@ enum Inner { #[cfg(test)] mod ut_version { - use super::Version; use std::convert::TryFrom; + use super::Version; + /// UT test cases for `Version::as_str`. /// /// # Brief diff --git a/ylong_http_client/examples/async_http.rs b/ylong_http_client/examples/async_http.rs index b69d544..a6edc7b 100644 --- a/ylong_http_client/examples/async_http.rs +++ b/ylong_http_client/examples/async_http.rs @@ -11,8 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! This is a simple asynchronous HTTP client example using the ylong_http_client crate. -//! It demonstrates creating a client, making a request, and reading the response asynchronously. +//! This is a simple asynchronous HTTP client example using the +//! ylong_http_client crate. It demonstrates creating a client, making a +//! request, and reading the response asynchronously. use ylong_http_client::async_impl::{Client, Downloader}; use ylong_http_client::{HttpClientError, Request}; diff --git a/ylong_http_client/examples/async_http2.rs b/ylong_http_client/examples/async_http2.rs index cb61855..0d16c7b 100644 --- a/ylong_http_client/examples/async_http2.rs +++ b/ylong_http_client/examples/async_http2.rs @@ -11,8 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! This is a simple asynchronous HTTP2 client example using the ylong_http_client crate. -//! It demonstrates creating a client, making a request, and reading the response asynchronously. +//! This is a simple asynchronous HTTP2 client example using the +//! ylong_http_client crate. It demonstrates creating a client, making a +//! request, and reading the response asynchronously. use ylong_http_client::async_impl::{Body, ClientBuilder}; use ylong_http_client::{HttpClientError, RequestBuilder, StatusCode, TextBody, Version}; diff --git a/ylong_http_client/examples/async_http2_multi.rs b/ylong_http_client/examples/async_http2_multi.rs index daa4a02..8886b20 100644 --- a/ylong_http_client/examples/async_http2_multi.rs +++ b/ylong_http_client/examples/async_http2_multi.rs @@ -11,10 +11,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! This is a simple asynchronous HTTP client example in concurrent scenarios using the ylong_http_client crate. -//! It demonstrates creating a client, making a request, and reading the response asynchronously. +//! This is a simple asynchronous HTTP client example in concurrent scenarios +//! using the ylong_http_client crate. It demonstrates creating a client, making +//! a request, and reading the response asynchronously. use std::sync::Arc; + use ylong_http_client::async_impl::{Body, ClientBuilder}; use ylong_http_client::{HttpClientError, RequestBuilder, StatusCode, TextBody, Version}; diff --git a/ylong_http_client/examples/async_proxy_http.rs b/ylong_http_client/examples/async_proxy_http.rs index ca71a6b..d59f602 100644 --- a/ylong_http_client/examples/async_proxy_http.rs +++ b/ylong_http_client/examples/async_proxy_http.rs @@ -11,8 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! This is a simple asynchronous HTTP client example using the ylong_http_client crate. -//! It demonstrates creating a client, making a request, and reading the response asynchronously. +//! This is a simple asynchronous HTTP client example using the +//! ylong_http_client crate. It demonstrates creating a client, making a +//! request, and reading the response asynchronously. use ylong_http_client::async_impl::{ClientBuilder, Downloader}; use ylong_http_client::{EmptyBody, HttpClientError, Proxy, Request}; diff --git a/ylong_http_client/examples/async_redirect_http.rs b/ylong_http_client/examples/async_redirect_http.rs index 500b984..2f2cf5c 100644 --- a/ylong_http_client/examples/async_redirect_http.rs +++ b/ylong_http_client/examples/async_redirect_http.rs @@ -11,8 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! This is a simple asynchronous HTTP client redirect example using the ylong_http_client crate. -//! It demonstrates creating a client, making a request, and reading the response asynchronously. +//! This is a simple asynchronous HTTP client redirect example using the +//! ylong_http_client crate. It demonstrates creating a client, making a +//! request, and reading the response asynchronously. use ylong_http_client::async_impl::{ClientBuilder, Downloader}; use ylong_http_client::{HttpClientError, Redirect, Request}; diff --git a/ylong_http_client/examples/sync_http.rs b/ylong_http_client/examples/sync_http.rs index 7b89bec..2a5289a 100644 --- a/ylong_http_client/examples/sync_http.rs +++ b/ylong_http_client/examples/sync_http.rs @@ -11,8 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! This is a simple synchronous HTTP client example using the ylong_http_client crate. -//! It demonstrates creating a client, making a request, and reading the response. +//! This is a simple synchronous HTTP client example using the ylong_http_client +//! crate. It demonstrates creating a client, making a request, and reading the +//! response. use ylong_http_client::sync_impl::{BodyReader, Client}; use ylong_http_client::{HttpClientError, Request}; diff --git a/ylong_http_client/examples/sync_proxy_http.rs b/ylong_http_client/examples/sync_proxy_http.rs index 216c537..fecb7ae 100644 --- a/ylong_http_client/examples/sync_proxy_http.rs +++ b/ylong_http_client/examples/sync_proxy_http.rs @@ -11,8 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! This is a simple synchronous HTTP client example using the ylong_http_client crate. -//! It demonstrates creating a client, making a request, and reading the response. +//! This is a simple synchronous HTTP client example using the ylong_http_client +//! crate. It demonstrates creating a client, making a request, and reading the +//! response. use ylong_http_client::sync_impl::{BodyReader, ClientBuilder}; use ylong_http_client::util::Proxy; use ylong_http_client::{EmptyBody, HttpClientError, Request}; diff --git a/ylong_http_client/examples/sync_redirect_http.rs b/ylong_http_client/examples/sync_redirect_http.rs index 8dc72da..6c7c431 100644 --- a/ylong_http_client/examples/sync_redirect_http.rs +++ b/ylong_http_client/examples/sync_redirect_http.rs @@ -11,8 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! This is a simple synchronous HTTP client redirect example using the ylong_http_client crate. -//! It demonstrates creating a client, making a request, and reading the response. +//! This is a simple synchronous HTTP client redirect example using the +//! ylong_http_client crate. It demonstrates creating a client, making a +//! request, and reading the response. use ylong_http_client::sync_impl::{BodyReader, ClientBuilder}; use ylong_http_client::util::Redirect; diff --git a/ylong_http_client/src/async_impl/adapter.rs b/ylong_http_client/src/async_impl/adapter.rs index 539b584..9df2376 100644 --- a/ylong_http_client/src/async_impl/adapter.rs +++ b/ylong_http_client/src/async_impl/adapter.rs @@ -11,10 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::async_impl::HttpBody; -use crate::{ErrorKind, HttpClientError}; use std::convert::TryFrom; use std::ops::{Deref, DerefMut}; + use ylong_http::body::async_impl::Body; use ylong_http::body::MultiPart; use ylong_http::error::HttpError; @@ -25,6 +24,9 @@ use ylong_http::request::{Request, RequestBuilder as ReqBuilder}; use ylong_http::response::Response as Resp; use ylong_http::version::Version; +use crate::async_impl::HttpBody; +use crate::{ErrorKind, HttpClientError}; + /// Response Adapter. pub struct Response { response: Resp, @@ -117,7 +119,7 @@ impl RequestBuilder { /// use ylong_http::headers::Headers; /// use ylong_http::request::RequestBuilder; /// - /// let request = RequestBuilder::new().header("ACCEPT","text/html"); + /// let request = RequestBuilder::new().header("ACCEPT", "text/html"); /// ``` pub fn header(mut self, name: N, value: V) -> Self where @@ -139,7 +141,7 @@ impl RequestBuilder { /// use ylong_http::headers::Headers; /// use ylong_http::request::RequestBuilder; /// - /// let request = RequestBuilder::new().append_header("ACCEPT","text/html"); + /// let request = RequestBuilder::new().append_header("ACCEPT", "text/html"); /// ``` pub fn append_header(mut self, name: N, value: V) -> Self where diff --git a/ylong_http_client/src/async_impl/client.rs b/ylong_http_client/src/async_impl/client.rs index 15970b5..6b4f6e4 100644 --- a/ylong_http_client/src/async_impl/client.rs +++ b/ylong_http_client/src/async_impl/client.rs @@ -11,22 +11,21 @@ // See the License for the specific language governing permissions and // limitations under the License. +use ylong_http::body::{ChunkBody, TextBody}; +use ylong_http::response::Response; + use super::{conn, Body, ConnPool, Connector, HttpBody, HttpConnector}; use crate::async_impl::timeout::TimeoutFuture; use crate::util::normalizer::{RequestFormatter, UriFormatter}; use crate::util::proxy::Proxies; use crate::util::redirect::TriggerKind; use crate::util::{ClientConfig, ConnectorConfig, HttpConfig, HttpVersion, Redirect}; -use crate::{sleep, timeout}; -use crate::{ErrorKind, HttpClientError, Proxy, Request, Timeout, Uri}; -use ylong_http::body::{ChunkBody, TextBody}; -use ylong_http::response::Response; - #[cfg(feature = "http2")] use crate::H2Config; +use crate::{sleep, timeout, ErrorKind, HttpClientError, Proxy, Request, Timeout, Uri}; -/// HTTP asynchronous client implementation. Users can use `async_impl::Client` to -/// send `Request` asynchronously. `async_impl::Client` depends on a +/// HTTP asynchronous client implementation. Users can use `async_impl::Client` +/// to send `Request` asynchronously. `async_impl::Client` depends on a /// [`async_impl::Connector`] that can be customized by the user. /// /// [`async_impl::Connector`]: Connector @@ -35,7 +34,7 @@ use crate::H2Config; /// /// ``` /// use ylong_http_client::async_impl::Client; -/// use ylong_http_client::{Request, EmptyBody}; +/// use ylong_http_client::{EmptyBody, Request}; /// /// async fn async_client() { /// // Creates a new `Client`. @@ -58,7 +57,8 @@ pub struct Client { } impl Client { - /// Creates a new, default `AsyncClient`, which uses [`async_impl::HttpConnector`]. + /// Creates a new, default `AsyncClient`, which uses + /// [`async_impl::HttpConnector`]. /// /// [`async_impl::HttpConnector`]: HttpConnector /// @@ -106,7 +106,7 @@ impl Client { /// /// ``` /// use ylong_http_client::async_impl::Client; - /// use ylong_http_client::{Request, EmptyBody}; + /// use ylong_http_client::{EmptyBody, Request}; /// /// async fn async_client() { /// let client = Client::new(); @@ -568,9 +568,7 @@ impl ClientBuilder { /// use ylong_http_client::async_impl::ClientBuilder; /// /// let builder = ClientBuilder::new() - /// .tls_cipher_list( - /// "DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK" - /// ); + /// .tls_cipher_list("DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK"); /// ``` pub fn tls_cipher_list(mut self, list: &str) -> Self { self.tls = self.tls.cipher_list(list); @@ -589,26 +587,24 @@ impl ClientBuilder { /// ``` /// use ylong_http_client::async_impl::ClientBuilder; /// - /// let builder = ClientBuilder::new() - /// .tls_cipher_suites( - /// "DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK" - /// ); + /// let builder = ClientBuilder::new().tls_cipher_suites( + /// "DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK", + /// ); /// ``` pub fn tls_cipher_suites(mut self, list: &str) -> Self { self.tls = self.tls.cipher_suites(list); self } - /// Controls the use of built-in system certificates during certificate validation. - /// Default to `true` -- uses built-in system certs. + /// Controls the use of built-in system certificates during certificate + /// validation. Default to `true` -- uses built-in system certs. /// /// # Examples /// /// ``` /// use ylong_http_client::async_impl::ClientBuilder; /// - /// let builder = ClientBuilder::new() - /// .tls_built_in_root_certs(false); + /// let builder = ClientBuilder::new().tls_built_in_root_certs(false); /// ``` pub fn tls_built_in_root_certs(mut self, is_use: bool) -> Self { self.tls = self.tls.build_in_root_certs(is_use); @@ -628,8 +624,7 @@ impl ClientBuilder { /// ``` /// use ylong_http_client::async_impl::ClientBuilder; /// - /// let builder = ClientBuilder::new() - /// .danger_accept_invalid_certs(true); + /// let builder = ClientBuilder::new().danger_accept_invalid_certs(true); /// ``` pub fn danger_accept_invalid_certs(mut self, is_invalid: bool) -> Self { self.tls = self.tls.danger_accept_invalid_certs(is_invalid); @@ -650,8 +645,7 @@ impl ClientBuilder { /// ``` /// use ylong_http_client::async_impl::ClientBuilder; /// - /// let builder = ClientBuilder::new() - /// .danger_accept_invalid_hostnames(true); + /// let builder = ClientBuilder::new().danger_accept_invalid_hostnames(true); /// ``` pub fn danger_accept_invalid_hostnames(mut self, is_invalid: bool) -> Self { self.tls = self.tls.danger_accept_invalid_hostnames(is_invalid); @@ -667,8 +661,7 @@ impl ClientBuilder { /// ``` /// use ylong_http_client::async_impl::ClientBuilder; /// - /// let builder = ClientBuilder::new() - /// .tls_sni(true); + /// let builder = ClientBuilder::new().tls_sni(true); /// ``` pub fn tls_sni(mut self, is_set_sni: bool) -> Self { self.tls = self.tls.sni(is_set_sni); @@ -690,7 +683,8 @@ mod ut_async_impl_client { /// /// # Brief /// 1. Creates a ClientBuilder by calling `Client::Builder`. - /// 2. Calls `http_config`, `client_config`, `build` on the builder respectively. + /// 2. Calls `http_config`, `client_config`, `build` on the builder + /// respectively. /// 3. Checks if the result is as expected. #[test] fn ut_client_builder() { @@ -702,7 +696,8 @@ mod ut_async_impl_client { /// /// # Brief /// 1. Creates a `ClientBuilder` by calling `ClientBuilder::default`. - /// 2. Calls `http_config`, `client_config`, `tls_config` and `build` respectively. + /// 2. Calls `http_config`, `client_config`, `tls_config` and `build` + /// respectively. /// 3. Checks if the result is as expected. #[cfg(feature = "__tls")] #[test] diff --git a/ylong_http_client/src/async_impl/conn/http1.rs b/ylong_http_client/src/async_impl/conn/http1.rs index a7c8b5f..0de0bf1 100644 --- a/ylong_http_client/src/async_impl/conn/http1.rs +++ b/ylong_http_client/src/async_impl/conn/http1.rs @@ -11,16 +11,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::pin::Pin; +use std::task::{Context, Poll}; + +use ylong_http::h1::{RequestEncoder, ResponseDecoder}; +use ylong_http::response::Response; + use crate::async_impl::{Body, HttpBody, StreamData}; use crate::error::{ErrorKind, HttpClientError}; use crate::util::dispatcher::http1::Http1Conn; use crate::util::normalizer::BodyLengthParser; -use crate::Request; -use crate::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, ReadBuf}; -use std::pin::Pin; -use std::task::{Context, Poll}; -use ylong_http::h1::{RequestEncoder, ResponseDecoder}; -use ylong_http::response::Response; +use crate::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, ReadBuf, Request}; const TEMP_BUF_SIZE: usize = 16 * 1024; diff --git a/ylong_http_client/src/async_impl/conn/http2.rs b/ylong_http_client/src/async_impl/conn/http2.rs index c432cb7..67a65d5 100644 --- a/ylong_http_client/src/async_impl/conn/http2.rs +++ b/ylong_http_client/src/async_impl/conn/http2.rs @@ -11,16 +11,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::async_impl::client::Retryable; -use crate::async_impl::conn::HttpBody; -use crate::async_impl::StreamData; -use crate::error::{ErrorKind, HttpClientError}; -use crate::util::dispatcher::http2::Http2Conn; -use crate::{AsyncRead, AsyncWrite, ReadBuf}; use std::cmp::min; use std::future::Future; use std::pin::Pin; use std::task::{Context, Poll}; + use ylong_http::body::async_impl::Body; use ylong_http::error::HttpError; use ylong_http::h2; @@ -31,6 +26,13 @@ use ylong_http::request::{Request, RequestPart}; use ylong_http::response::status::StatusCode; use ylong_http::response::{Response, ResponsePart}; +use crate::async_impl::client::Retryable; +use crate::async_impl::conn::HttpBody; +use crate::async_impl::StreamData; +use crate::error::{ErrorKind, HttpClientError}; +use crate::util::dispatcher::http2::Http2Conn; +use crate::{AsyncRead, AsyncWrite, ReadBuf}; + const UNUSED_FLAG: u8 = 0x0; pub(crate) async fn request( @@ -45,7 +47,9 @@ where let part = request.part().clone(); let body = request.body_mut(); - // TODO Due to the reason of the Body structure, the use of the trailer is not implemented here for the time being, and it needs to be completed after the Body trait is provided to obtain the trailer interface + // TODO Due to the reason of the Body structure, the use of the trailer is not + // implemented here for the time being, and it needs to be completed after the + // Body trait is provided to obtain the trailer interface match build_data_frame(conn.id as usize, body).await? { None => { let headers = build_headers_frame(conn.id, part, true) @@ -173,7 +177,8 @@ pub(crate) async fn build_data_frame( if data_vec.is_empty() { Ok(None) } else { - // TODO When the Body trait supports trailer, END_STREAM_FLAG needs to be modified + // TODO When the Body trait supports trailer, END_STREAM_FLAG needs to be + // modified let mut flag = FrameFlags::new(UNUSED_FLAG); flag.set_end_stream(true); Ok(Some(Frame::new( @@ -248,7 +253,8 @@ fn build_pseudo_headers(request_part: &RequestPart) -> PseudoHeaders { .path_and_query() .or_else(|| Some(String::from("/"))), ); - // TODO Validity verification is required, for example: `Authority` must be consistent with the `Host` header + // TODO Validity verification is required, for example: `Authority` must be + // consistent with the `Host` header pseudo.set_authority(request_part.uri.authority().map(|auth| auth.to_string())); pseudo } @@ -376,11 +382,12 @@ impl AsyncRead for Te #[cfg(feature = "http2")] #[cfg(test)] mod ut_http2 { - use crate::async_impl::conn::http2::{build_data_frame, build_headers_frame}; use ylong_http::body::TextBody; use ylong_http::h2::{ErrorCode, H2Error, Payload}; use ylong_http::request::RequestBuilder; + use crate::async_impl::conn::http2::{build_data_frame, build_headers_frame}; + macro_rules! build_request { ( Request: { diff --git a/ylong_http_client/src/async_impl/conn/mod.rs b/ylong_http_client/src/async_impl/conn/mod.rs index 9b01201..1bc9914 100644 --- a/ylong_http_client/src/async_impl/conn/mod.rs +++ b/ylong_http_client/src/async_impl/conn/mod.rs @@ -11,15 +11,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +use ylong_http::body::async_impl::Body; +use ylong_http::request::Request; +use ylong_http::response::Response; + +use crate::async_impl::client::Retryable; use crate::async_impl::HttpBody; use crate::error::HttpClientError; use crate::util::dispatcher::Conn; use crate::{AsyncRead, AsyncWrite}; -use ylong_http::body::async_impl::Body; - -use crate::async_impl::client::Retryable; -use ylong_http::request::Request; -use ylong_http::response::Response; #[cfg(feature = "http1_1")] mod http1; diff --git a/ylong_http_client/src/async_impl/connector.rs b/ylong_http_client/src/async_impl/connector.rs index 8802fa7..db23445 100644 --- a/ylong_http_client/src/async_impl/connector.rs +++ b/ylong_http_client/src/async_impl/connector.rs @@ -13,19 +13,21 @@ //! Asynchronous `Connector` trait and `HttpConnector` implementation. -use crate::util::ConnectorConfig; -use crate::{AsyncRead, AsyncWrite, TcpStream, Uri}; use core::future::Future; use std::error::Error; use std::io; use std::net::ToSocketAddrs; +use crate::util::ConnectorConfig; +use crate::{AsyncRead, AsyncWrite, TcpStream, Uri}; + /// `Connector` trait used by `async_impl::Client`. `Connector` provides /// asynchronous connection establishment interfaces. pub trait Connector { /// Streams that this connector produces. type Stream: AsyncRead + AsyncWrite + Unpin + Sync + Send + 'static; - /// Possible errors that this connector may generate when attempting to connect. + /// Possible errors that this connector may generate when attempting to + /// connect. type Error: Into>; /// Futures generated by this connector when attempting to create a stream. type Future: Future> + Unpin + Sync + Send + 'static; @@ -70,12 +72,13 @@ async fn tcp_stream(addr: &str) -> io::Result { #[cfg(not(feature = "__tls"))] mod no_tls { - use super::{tcp_stream, Connector, HttpConnector}; - use crate::{TcpStream, Uri}; use core::future::Future; use core::pin::Pin; use std::io::Error; + use super::{tcp_stream, Connector, HttpConnector}; + use crate::{TcpStream, Uri}; + impl Connector for HttpConnector { type Stream = TcpStream; type Error = Error; @@ -98,13 +101,14 @@ mod no_tls { #[cfg(feature = "__tls")] mod tls { + use core::future::Future; + use core::pin::Pin; + use std::io::{Error, ErrorKind, Write}; + use super::{tcp_stream, Connector, HttpConnector}; use crate::async_impl::ssl_stream::{AsyncSslStream, MixStream}; use crate::error::CauseMessage; use crate::{AsyncReadExt, AsyncWriteExt, Scheme, TcpStream, Uri}; - use core::future::Future; - use core::pin::Pin; - use std::io::{Error, ErrorKind, Write}; impl Connector for HttpConnector { type Stream = MixStream; diff --git a/ylong_http_client/src/async_impl/downloader/builder.rs b/ylong_http_client/src/async_impl/downloader/builder.rs index c80aa05..01c480e 100644 --- a/ylong_http_client/src/async_impl/downloader/builder.rs +++ b/ylong_http_client/src/async_impl/downloader/builder.rs @@ -33,7 +33,8 @@ pub struct DownloaderBuilder { state: S, } -/// A state indicates that `DownloaderBuilder` wants a body that needs to be downloaded. +/// A state indicates that `DownloaderBuilder` wants a body that needs to be +/// downloaded. pub struct WantsBody; impl DownloaderBuilder { @@ -171,7 +172,10 @@ impl DownloaderBuilder> { /// # use ylong_http_client::Timeout; /// /// # async fn set_timeout(body: Response) { - /// let builder = DownloaderBuilder::new().body(body).console().timeout(Timeout::none()); + /// let builder = DownloaderBuilder::new() + /// .body(body) + /// .console() + /// .timeout(Timeout::none()); /// # } /// ``` pub fn timeout(mut self, timeout: Timeout) -> Self { @@ -190,7 +194,10 @@ impl DownloaderBuilder> { /// # use ylong_http_client::SpeedLimit; /// /// # async fn set_timeout(body: Response) { - /// let builder = DownloaderBuilder::new().body(body).console().speed_limit(SpeedLimit::none()); + /// let builder = DownloaderBuilder::new() + /// .body(body) + /// .console() + /// .speed_limit(SpeedLimit::none()); /// # } /// ``` pub fn speed_limit(mut self, speed_limit: SpeedLimit) -> Self { diff --git a/ylong_http_client/src/async_impl/downloader/mod.rs b/ylong_http_client/src/async_impl/downloader/mod.rs index 77e0b92..b3c6196 100644 --- a/ylong_http_client/src/async_impl/downloader/mod.rs +++ b/ylong_http_client/src/async_impl/downloader/mod.rs @@ -14,17 +14,17 @@ mod builder; mod operator; -use builder::WantsBody; -use operator::Console; +use std::time::Instant; pub use builder::DownloaderBuilder; +use builder::WantsBody; +use operator::Console; pub use operator::{DownloadFuture, DownloadOperator, ProgressFuture}; +use ylong_http::body::async_impl::Body; // TODO: Adapter, use Response later. use crate::async_impl::Response; use crate::{ErrorKind, HttpClientError, SpeedLimit, Timeout}; -use std::time::Instant; -use ylong_http::body::async_impl::Body; /// A downloader that can help you download the response body. /// @@ -88,7 +88,7 @@ use ylong_http::body::async_impl::Body; /// self: Pin<&mut Self>, /// cx: &mut Context<'_>, /// downloaded: u64, -/// total: Option +/// total: Option, /// ) -> Poll> { /// // Writes your customize method. /// todo!() diff --git a/ylong_http_client/src/async_impl/downloader/operator.rs b/ylong_http_client/src/async_impl/downloader/operator.rs index afe387d..5fbba43 100644 --- a/ylong_http_client/src/async_impl/downloader/operator.rs +++ b/ylong_http_client/src/async_impl/downloader/operator.rs @@ -11,14 +11,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::HttpClientError; use std::future::Future; use std::pin::Pin; use std::task::{Context, Poll}; -/// The trait defines the functionality required for processing bodies of HTTP messages. +use crate::HttpClientError; + +/// The trait defines the functionality required for processing bodies of HTTP +/// messages. pub trait DownloadOperator { - /// Attempts to write the body data read each time to the specified location. + /// Attempts to write the body data read each time to the specified + /// location. /// /// This method will be called every time a part of the body data is read. fn poll_download( diff --git a/ylong_http_client/src/async_impl/http_body.rs b/ylong_http_client/src/async_impl/http_body.rs index 7fd882a..a20fa8f 100644 --- a/ylong_http_client/src/async_impl/http_body.rs +++ b/ylong_http_client/src/async_impl/http_body.rs @@ -11,23 +11,22 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::{Body, StreamData}; - -use crate::error::{ErrorKind, HttpClientError}; -use crate::{AsyncRead, ReadBuf, Sleep}; use core::pin::Pin; use core::task::{Context, Poll}; use std::future::Future; use std::io::{Cursor, Read}; -use ylong_http::body::TextBodyDecoder; -use ylong_http::headers::Headers; +use ylong_http::body::TextBodyDecoder; +#[cfg(feature = "http1_1")] +use ylong_http::body::{ChunkBodyDecoder, ChunkState}; +use ylong_http::headers::Headers; #[cfg(feature = "http1_1")] use ylong_http::headers::{HeaderName, HeaderValue}; +use super::{Body, StreamData}; +use crate::error::{ErrorKind, HttpClientError}; use crate::util::normalizer::BodyLength; -#[cfg(feature = "http1_1")] -use ylong_http::body::{ChunkBodyDecoder, ChunkState}; +use crate::{AsyncRead, ReadBuf, Sleep}; /// `HttpBody` is the body part of the `Response` returned by `Client::request`. /// `HttpBody` implements `Body` trait, so users can call related methods to get @@ -36,8 +35,8 @@ use ylong_http::body::{ChunkBodyDecoder, ChunkState}; /// # Examples /// /// ```no_run -/// use ylong_http_client::async_impl::{Client, HttpBody, Body}; -/// use ylong_http_client::{Request, EmptyBody}; +/// use ylong_http_client::async_impl::{Body, Client, HttpBody}; +/// use ylong_http_client::{EmptyBody, Request}; /// /// async fn read_body() { /// let client = Client::new(); @@ -563,9 +562,10 @@ impl Chunk { #[cfg(test)] mod ut_async_http_body { - use crate::async_impl::http_body::Chunk; use ylong_http::body::ChunkBodyDecoder; + use crate::async_impl::http_body::Chunk; + /// UT test cases for `Chunk::get_trailers`. /// /// # Brief diff --git a/ylong_http_client/src/async_impl/mod.rs b/ylong_http_client/src/async_impl/mod.rs index 3a85470..9d12adb 100644 --- a/ylong_http_client/src/async_impl/mod.rs +++ b/ylong_http_client/src/async_impl/mod.rs @@ -33,16 +33,15 @@ mod timeout; mod uploader; pub use client::ClientBuilder; - +pub(crate) use conn::StreamData; pub use connector::Connector; +pub(crate) use connector::HttpConnector; pub use downloader::{DownloadOperator, Downloader, DownloaderBuilder}; pub use http_body::HttpBody; -pub use uploader::{UploadOperator, Uploader, UploaderBuilder}; -pub use ylong_http::body::{async_impl::Body, MultiPart, Part}; - -pub(crate) use conn::StreamData; -pub(crate) use connector::HttpConnector; pub(crate) use pool::ConnPool; +pub use uploader::{UploadOperator, Uploader, UploaderBuilder}; +pub use ylong_http::body::async_impl::Body; +pub use ylong_http::body::{MultiPart, Part}; #[cfg(feature = "__tls")] mod ssl_stream; diff --git a/ylong_http_client/src/async_impl/pool.rs b/ylong_http_client/src/async_impl/pool.rs index 366b525..269500a 100644 --- a/ylong_http_client/src/async_impl/pool.rs +++ b/ylong_http_client/src/async_impl/pool.rs @@ -11,17 +11,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::async_impl::Connector; -use crate::error::HttpClientError; -use crate::util::dispatcher::{Conn, ConnDispatcher, Dispatcher}; -use crate::util::pool::{Pool, PoolKey}; -use crate::{AsyncRead, AsyncWrite}; -use crate::{ErrorKind, HttpConfig, HttpVersion, Uri}; use std::error::Error; use std::future::Future; use std::mem::take; use std::sync::{Arc, Mutex}; +use crate::async_impl::Connector; +use crate::error::HttpClientError; +use crate::util::dispatcher::{Conn, ConnDispatcher, Dispatcher}; +use crate::util::pool::{Pool, PoolKey}; +use crate::{AsyncRead, AsyncWrite, ErrorKind, HttpConfig, HttpVersion, Uri}; + pub(crate) struct ConnPool { pool: Pool>, connector: Arc, @@ -93,7 +93,8 @@ impl Conns { #[cfg(feature = "http2")] HttpVersion::Http2PriorKnowledge => { { - // The lock `h2_occupation` is used to prevent multiple coroutines from sending Requests at the same time under concurrent conditions, + // The lock `h2_occupation` is used to prevent multiple coroutines from sending + // Requests at the same time under concurrent conditions, // resulting in the creation of multiple tcp connections let _lock = self.h2_occupation.lock().await; if let Some(conn) = self.get_exist_conn() { diff --git a/ylong_http_client/src/async_impl/ssl_stream/c_ssl_stream.rs b/ylong_http_client/src/async_impl/ssl_stream/c_ssl_stream.rs index ad913c2..4b2ebb7 100644 --- a/ylong_http_client/src/async_impl/ssl_stream/c_ssl_stream.rs +++ b/ylong_http_client/src/async_impl/ssl_stream/c_ssl_stream.rs @@ -11,20 +11,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::async_impl::ssl_stream::{check_io_to_poll, Wrapper}; -use crate::util::c_openssl::{ - error::ErrorStack, - ssl::{self, ShutdownResult, Ssl, SslErrorCode}, -}; -use crate::{AsyncRead, AsyncWrite, ReadBuf}; -use core::{ - future, - pin::Pin, - ptr, slice, - task::{Context, Poll}, -}; +use core::pin::Pin; +use core::task::{Context, Poll}; +use core::{future, ptr, slice}; use std::io::{self, Read, Write}; +use crate::async_impl::ssl_stream::{check_io_to_poll, Wrapper}; +use crate::util::c_openssl::error::ErrorStack; +use crate::util::c_openssl::ssl::{self, ShutdownResult, Ssl, SslErrorCode}; +use crate::{AsyncRead, AsyncWrite, ReadBuf}; + /// An asynchronous version of [`openssl::ssl::SslStream`]. #[derive(Debug)] pub struct AsyncSslStream(ssl::SslStream>); @@ -129,12 +125,14 @@ where fn poll_shutdown(mut self: Pin<&mut Self>, ctx: &mut Context) -> Poll> { // Shuts down the session. match self.as_mut().with_context(ctx, |s| s.shutdown()) { - // Sends a close notify message to the peer, after which `ShutdownResult::Sent` is returned. - // Awaits the receipt of a close notify message from the peer, after which `ShutdownResult::Received` is returned. + // Sends a close notify message to the peer, after which `ShutdownResult::Sent` is + // returned. Awaits the receipt of a close notify message from the peer, + // after which `ShutdownResult::Received` is returned. Ok(ShutdownResult::Sent) | Ok(ShutdownResult::Received) => {} // The SSL session has been closed. Err(ref e) if e.code() == SslErrorCode::ZERO_RETURN => {} - // When the underlying BIO could not satisfy the needs of SSL_shutdown() to continue the handshake + // When the underlying BIO could not satisfy the needs of SSL_shutdown() to continue the + // handshake Err(ref e) if e.code() == SslErrorCode::WANT_READ || e.code() == SslErrorCode::WANT_WRITE => { diff --git a/ylong_http_client/src/async_impl/ssl_stream/mix.rs b/ylong_http_client/src/async_impl/ssl_stream/mix.rs index f45d576..1c03a43 100644 --- a/ylong_http_client/src/async_impl/ssl_stream/mix.rs +++ b/ylong_http_client/src/async_impl/ssl_stream/mix.rs @@ -11,12 +11,11 @@ // See the License for the specific language governing permissions and // limitations under the License. +use core::pin::Pin; +use core::task::{Context, Poll}; + use crate::async_impl::ssl_stream::AsyncSslStream; use crate::{AsyncRead, AsyncWrite, ReadBuf}; -use core::{ - pin::Pin, - task::{Context, Poll}, -}; /// A stream which may be wrapped with TLS. pub enum MixStream { diff --git a/ylong_http_client/src/async_impl/ssl_stream/mod.rs b/ylong_http_client/src/async_impl/ssl_stream/mod.rs index 502aa28..5088776 100644 --- a/ylong_http_client/src/async_impl/ssl_stream/mod.rs +++ b/ylong_http_client/src/async_impl/ssl_stream/mod.rs @@ -19,5 +19,4 @@ mod wrapper; #[cfg(feature = "__c_openssl")] pub use c_ssl_stream::AsyncSslStream; pub use mix::MixStream; - pub(crate) use wrapper::{check_io_to_poll, Wrapper}; diff --git a/ylong_http_client/src/async_impl/ssl_stream/wrapper.rs b/ylong_http_client/src/async_impl/ssl_stream/wrapper.rs index 7980dd6..b51e2a6 100644 --- a/ylong_http_client/src/async_impl/ssl_stream/wrapper.rs +++ b/ylong_http_client/src/async_impl/ssl_stream/wrapper.rs @@ -11,26 +11,26 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{AsyncRead, AsyncWrite, ReadBuf}; -use core::{ - fmt::Debug, - pin::Pin, - task::{Context, Poll}, -}; +use core::fmt::Debug; +use core::pin::Pin; +use core::task::{Context, Poll}; use std::io::{self, Read, Write}; +use crate::{AsyncRead, AsyncWrite, ReadBuf}; + #[derive(Debug)] pub(crate) struct Wrapper { pub(crate) stream: S, - pub(crate) context: *mut (), // Context of stream. + // Context of stream. + pub(crate) context: *mut (), } impl Wrapper { /// Gets inner `Stream` and `Context` of `Stream`. /// /// # SAFETY - /// Must be called with `context` set to a valid pointer to a live `Context` object, - /// and the wrapper must be pinned in memory. + /// Must be called with `context` set to a valid pointer to a live `Context` + /// object, and the wrapper must be pinned in memory. unsafe fn inner(&mut self) -> (Pin<&mut S>, &mut Context<'_>) { debug_assert!(!self.context.is_null()); let stream = Pin::new_unchecked(&mut self.stream); diff --git a/ylong_http_client/src/async_impl/timeout.rs b/ylong_http_client/src/async_impl/timeout.rs index 19ddb0d..041c21b 100644 --- a/ylong_http_client/src/async_impl/timeout.rs +++ b/ylong_http_client/src/async_impl/timeout.rs @@ -11,14 +11,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::async_impl::HttpBody; -use crate::Sleep; -use crate::{ErrorKind, HttpClientError}; use std::future::Future; use std::pin::Pin; use std::task::{Context, Poll}; + use ylong_http::response::Response; +use crate::async_impl::HttpBody; +use crate::{ErrorKind, HttpClientError, Sleep}; + pub(crate) struct TimeoutFuture { pub(crate) timeout: Option>>, pub(crate) future: T, diff --git a/ylong_http_client/src/async_impl/uploader/builder.rs b/ylong_http_client/src/async_impl/uploader/builder.rs index 627ec06..58017c2 100644 --- a/ylong_http_client/src/async_impl/uploader/builder.rs +++ b/ylong_http_client/src/async_impl/uploader/builder.rs @@ -24,7 +24,10 @@ use crate::AsyncRead; /// ``` /// # use ylong_http_client::async_impl::{UploaderBuilder, Uploader}; /// -/// let uploader = UploaderBuilder::new().reader("HelloWorld".as_bytes()).console().build(); +/// let uploader = UploaderBuilder::new() +/// .reader("HelloWorld".as_bytes()) +/// .console() +/// .build(); /// ``` pub struct UploaderBuilder { state: S, @@ -118,13 +121,15 @@ impl UploaderBuilder> { /// self: Pin<&mut Self>, /// cx: &mut Context<'_>, /// uploaded: u64, - /// total: Option + /// total: Option, /// ) -> Poll> { /// todo!() /// } /// } /// - /// let builder = UploaderBuilder::new().reader("HelloWorld".as_bytes()).operator(MyOperator); + /// let builder = UploaderBuilder::new() + /// .reader("HelloWorld".as_bytes()) + /// .operator(MyOperator); /// ``` pub fn operator(self, operator: T) -> UploaderBuilder> { UploaderBuilder { @@ -147,7 +152,9 @@ impl UploaderBuilder> { /// # use ylong_http_client::async_impl::{UploaderBuilder, Uploader}; /// # use ylong_http_client::Response; /// - /// let builder = UploaderBuilder::new().reader("HelloWorld".as_bytes()).console(); + /// let builder = UploaderBuilder::new() + /// .reader("HelloWorld".as_bytes()) + /// .console(); /// ``` pub fn console(self) -> UploaderBuilder> { UploaderBuilder { @@ -170,7 +177,8 @@ pub struct WantsConfig { impl UploaderBuilder> { /// Sets the total bytes of the uploaded content. /// - /// Default is `None` which means that you don't know the size of the content. + /// Default is `None` which means that you don't know the size of the + /// content. /// /// # Examples /// diff --git a/ylong_http_client/src/async_impl/uploader/mod.rs b/ylong_http_client/src/async_impl/uploader/mod.rs index fde6627..a65b513 100644 --- a/ylong_http_client/src/async_impl/uploader/mod.rs +++ b/ylong_http_client/src/async_impl/uploader/mod.rs @@ -14,15 +14,15 @@ mod builder; mod operator; -pub use builder::{UploaderBuilder, WantsReader}; -pub use operator::{Console, UploadOperator}; - -use crate::{AsyncRead, ReadBuf}; -use crate::{ErrorKind, HttpClientError}; use std::pin::Pin; use std::task::{Context, Poll}; + +pub use builder::{UploaderBuilder, WantsReader}; +pub use operator::{Console, UploadOperator}; use ylong_http::body::async_impl::Body; +use crate::{AsyncRead, ErrorKind, HttpClientError, ReadBuf}; + /// An uploader that can help you upload the request body. /// /// An `Uploader` provides a template method for uploading a file or a slice and @@ -70,7 +70,7 @@ use ylong_http::body::async_impl::Body; /// self: Pin<&mut Self>, /// cx: &mut Context<'_>, /// uploaded: u64, -/// total: Option +/// total: Option, /// ) -> Poll> { /// todo!() /// } @@ -78,7 +78,10 @@ use ylong_http::body::async_impl::Body; /// /// // Creates a default `Uploader` based on `MyUploadOperator`. /// // Configures your uploader by using `UploaderBuilder`. -/// let uploader = Uploader::builder().reader("HelloWorld".as_bytes()).operator(MyUploadOperator).build(); +/// let uploader = Uploader::builder() +/// .reader("HelloWorld".as_bytes()) +/// .operator(MyUploadOperator) +/// .build(); /// # } /// ``` pub struct Uploader { @@ -89,7 +92,8 @@ pub struct Uploader { } impl Uploader { - /// Creates an `Uploader` with a `Console` operator which displays process on console. + /// Creates an `Uploader` with a `Console` operator which displays process + /// on console. /// /// # Examples /// diff --git a/ylong_http_client/src/async_impl/uploader/operator.rs b/ylong_http_client/src/async_impl/uploader/operator.rs index ad62c53..5304276 100644 --- a/ylong_http_client/src/async_impl/uploader/operator.rs +++ b/ylong_http_client/src/async_impl/uploader/operator.rs @@ -11,11 +11,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::HttpClientError; use std::future::Future; use std::pin::Pin; use std::task::{Context, Poll}; +use crate::HttpClientError; + /// A `UploadOperator` represents structures that can read local data to socket. /// /// You can implement `UploadOperator` for your structures and pass it to a @@ -39,7 +40,7 @@ use std::task::{Context, Poll}; /// self: Pin<&mut Self>, /// cx: &mut Context<'_>, /// uploaded: u64, -/// total: Option +/// total: Option, /// ) -> Poll> { /// todo!() /// } diff --git a/ylong_http_client/src/error.rs b/ylong_http_client/src/error.rs index f6a009b..e6d6a69 100644 --- a/ylong_http_client/src/error.rs +++ b/ylong_http_client/src/error.rs @@ -17,7 +17,8 @@ use core::fmt::{Debug, Display, Formatter}; use std::error::Error; -/// The structure encapsulates errors that can be encountered when working with the HTTP client. +/// The structure encapsulates errors that can be encountered when working with +/// the HTTP client. pub struct HttpClientError { kind: ErrorKind, cause: Option>, diff --git a/ylong_http_client/src/lib.rs b/ylong_http_client/src/lib.rs index 22393d9..7a21577 100644 --- a/ylong_http_client/src/lib.rs +++ b/ylong_http_client/src/lib.rs @@ -12,18 +12,20 @@ // limitations under the License. //! `ylong_http_client` provides a HTTP client that based on `ylong_http` crate. -//! You can use the client to send request to a server, and then get the response. +//! You can use the client to send request to a server, and then get the +//! response. //! //! # Supported HTTP Version //! - HTTP1.1 -//! // TODO: Need doc. // ylong_http crate re-export. pub use ylong_http::body::{EmptyBody, TextBody}; +pub use ylong_http::request::method::Method; pub use ylong_http::request::uri::{Scheme, Uri}; -pub use ylong_http::request::{method::Method, Request, RequestPart}; -pub use ylong_http::response::{status::StatusCode, ResponsePart}; +pub use ylong_http::request::{Request, RequestPart}; +pub use ylong_http::response::status::StatusCode; +pub use ylong_http::response::ResponsePart; pub use ylong_http::version::Version; #[cfg(all(feature = "async", any(feature = "http1_1", feature = "http2")))] @@ -53,34 +55,30 @@ pub use error::{ErrorKind, HttpClientError}; ))] pub mod util; -#[cfg(all( - any(feature = "async", feature = "sync"), - any(feature = "http1_1", feature = "http2"), -))] -pub use util::*; - +#[cfg(all(feature = "tokio_base", feature = "http2"))] +pub(crate) use tokio::sync::{ + mpsc::{error::TryRecvError, unbounded_channel, UnboundedReceiver, UnboundedSender}, + Mutex as AsyncMutex, MutexGuard, +}; #[cfg(all(feature = "tokio_base", feature = "async"))] pub(crate) use tokio::{ io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, ReadBuf}, net::TcpStream, time::{sleep, timeout, Sleep}, }; - -#[cfg(all(feature = "tokio_base", feature = "http2"))] -pub(crate) use tokio::sync::{ - mpsc::{error::TryRecvError, unbounded_channel, UnboundedReceiver, UnboundedSender}, - Mutex as AsyncMutex, MutexGuard, +#[cfg(all( + any(feature = "async", feature = "sync"), + any(feature = "http1_1", feature = "http2"), +))] +pub use util::*; +#[cfg(all(feature = "ylong_base", feature = "http2"))] +pub(crate) use ylong_runtime::sync::{ + mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender}, + Mutex as AsyncMutex, MutexGuard, RecvError as TryRecvError, }; - #[cfg(feature = "ylong_base")] pub(crate) use ylong_runtime::{ io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, ReadBuf}, net::TcpStream, time::{sleep, timeout, Sleep}, }; - -#[cfg(all(feature = "ylong_base", feature = "http2"))] -pub(crate) use ylong_runtime::sync::{ - mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender}, - Mutex as AsyncMutex, MutexGuard, RecvError as TryRecvError, -}; diff --git a/ylong_http_client/src/sync_impl/client.rs b/ylong_http_client/src/sync_impl/client.rs index 371b42c..95f2a33 100644 --- a/ylong_http_client/src/sync_impl/client.rs +++ b/ylong_http_client/src/sync_impl/client.rs @@ -11,6 +11,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +use ylong_http::request::uri::Uri; +// TODO: Adapter, remove this later. +use ylong_http::response::Response; + use super::{Body, Connector, HttpBody, HttpConnector}; use crate::error::HttpClientError; use crate::sync_impl::conn; @@ -18,13 +22,10 @@ use crate::sync_impl::pool::ConnPool; use crate::util::normalizer::RequestFormatter; use crate::util::proxy::Proxies; use crate::util::redirect::TriggerKind; -use crate::util::{ClientConfig, HttpConfig, HttpVersion, Proxy, Timeout}; -use crate::util::{ConnectorConfig, Redirect}; +use crate::util::{ + ClientConfig, ConnectorConfig, HttpConfig, HttpVersion, Proxy, Redirect, Timeout, +}; use crate::Request; -use ylong_http::request::uri::Uri; - -// TODO: Adapter, remove this later. -use ylong_http::response::Response; /// HTTP synchronous client implementation. Users can use `Client` to /// send `Request` synchronously. `Client` depends on a `Connector` that @@ -34,7 +35,7 @@ use ylong_http::response::Response; /// /// ```no_run /// use ylong_http_client::sync_impl::Client; -/// use ylong_http_client::{Request, EmptyBody}; +/// use ylong_http_client::{EmptyBody, Request}; /// /// // Creates a new `Client`. /// let client = Client::new(); @@ -54,7 +55,8 @@ pub struct Client { } impl Client { - /// Creates a new, default `Client`, which uses [`sync_impl::HttpConnector`]. + /// Creates a new, default `Client`, which uses + /// [`sync_impl::HttpConnector`]. /// /// [`sync_impl::HttpConnector`]: HttpConnector /// @@ -101,7 +103,7 @@ impl Client { /// /// ```no_run /// use ylong_http_client::sync_impl::Client; - /// use ylong_http_client::{Request, EmptyBody}; + /// use ylong_http_client::{EmptyBody, Request}; /// /// let client = Client::new(); /// let response = client.request(Request::new(EmptyBody)); @@ -420,9 +422,7 @@ impl ClientBuilder { /// use ylong_http_client::sync_impl::ClientBuilder; /// /// let builder = ClientBuilder::new() - /// .tls_cipher_list( - /// "DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK" - /// ); + /// .tls_cipher_list("DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK"); /// ``` pub fn tls_cipher_list(mut self, list: &str) -> Self { self.tls = self.tls.cipher_list(list); @@ -441,26 +441,24 @@ impl ClientBuilder { /// ``` /// use ylong_http_client::sync_impl::ClientBuilder; /// - /// let builder = ClientBuilder::new() - /// .tls_cipher_suites( - /// "DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK" - /// ); + /// let builder = ClientBuilder::new().tls_cipher_suites( + /// "DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK", + /// ); /// ``` pub fn tls_cipher_suites(mut self, list: &str) -> Self { self.tls = self.tls.cipher_suites(list); self } - /// Controls the use of built-in system certificates during certificate validation. - /// Default to `true` -- uses built-in system certs. + /// Controls the use of built-in system certificates during certificate + /// validation. Default to `true` -- uses built-in system certs. /// /// # Examples /// /// ``` /// use ylong_http_client::sync_impl::ClientBuilder; /// - /// let builder = ClientBuilder::new() - /// .tls_built_in_root_certs(false); + /// let builder = ClientBuilder::new().tls_built_in_root_certs(false); /// ``` pub fn tls_built_in_root_certs(mut self, is_use: bool) -> Self { self.tls = self.tls.build_in_root_certs(is_use); @@ -480,8 +478,7 @@ impl ClientBuilder { /// ``` /// use ylong_http_client::sync_impl::ClientBuilder; /// - /// let builder = ClientBuilder::new() - /// .danger_accept_invalid_certs(true); + /// let builder = ClientBuilder::new().danger_accept_invalid_certs(true); /// ``` pub fn danger_accept_invalid_certs(mut self, is_invalid: bool) -> Self { self.tls = self.tls.danger_accept_invalid_certs(is_invalid); @@ -502,8 +499,7 @@ impl ClientBuilder { /// ``` /// use ylong_http_client::sync_impl::ClientBuilder; /// - /// let builder = ClientBuilder::new() - /// .danger_accept_invalid_hostnames(true); + /// let builder = ClientBuilder::new().danger_accept_invalid_hostnames(true); /// ``` pub fn danger_accept_invalid_hostnames(mut self, is_invalid: bool) -> Self { self.tls = self.tls.danger_accept_invalid_hostnames(is_invalid); @@ -519,8 +515,7 @@ impl ClientBuilder { /// ``` /// use ylong_http_client::sync_impl::ClientBuilder; /// - /// let builder = ClientBuilder::new() - /// .tls_sni(true); + /// let builder = ClientBuilder::new().tls_sni(true); /// ``` pub fn tls_sni(mut self, is_set_sni: bool) -> Self { self.tls = self.tls.sni(is_set_sni); @@ -536,11 +531,12 @@ impl Default for ClientBuilder { #[cfg(test)] mod ut_syn_client { - use crate::sync_impl::Client; use ylong_http::body::TextBody; use ylong_http::request::uri::Uri; use ylong_http::request::Request; + use crate::sync_impl::Client; + /// UT test cases for `Client::request`. /// /// # Brief @@ -575,7 +571,8 @@ mod ut_syn_client { /// /// # Brief /// 1. Creates a `Client` by calling `Client::builder`. - /// 2. Calls `http_config`, `client_config`, `tls_config` and `build` respectively. + /// 2. Calls `http_config`, `client_config`, `tls_config` and `build` + /// respectively. /// 3. Checks if the result is correct. #[cfg(feature = "__tls")] #[test] diff --git a/ylong_http_client/src/sync_impl/conn/http1.rs b/ylong_http_client/src/sync_impl/conn/http1.rs index 2234e0a..8cfaa92 100644 --- a/ylong_http_client/src/sync_impl/conn/http1.rs +++ b/ylong_http_client/src/sync_impl/conn/http1.rs @@ -11,17 +11,18 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::io::{Read, Write}; + +use ylong_http::body::sync_impl::Body; +use ylong_http::h1::{RequestEncoder, ResponseDecoder}; +// TODO: Adapter, remove this later. +use ylong_http::response::Response; + use crate::error::{ErrorKind, HttpClientError}; use crate::sync_impl::conn::StreamData; use crate::sync_impl::HttpBody; use crate::util::dispatcher::http1::Http1Conn; use crate::Request; -use std::io::{Read, Write}; -use ylong_http::body::sync_impl::Body; -use ylong_http::h1::{RequestEncoder, ResponseDecoder}; - -// TODO: Adapter, remove this later. -use ylong_http::response::Response; const TEMP_BUF_SIZE: usize = 16 * 1024; diff --git a/ylong_http_client/src/sync_impl/conn/mod.rs b/ylong_http_client/src/sync_impl/conn/mod.rs index 055b3a9..0c94355 100644 --- a/ylong_http_client/src/sync_impl/conn/mod.rs +++ b/ylong_http_client/src/sync_impl/conn/mod.rs @@ -11,14 +11,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::error::HttpClientError; -use crate::sync_impl::HttpBody; -use crate::util::dispatcher::Conn; use std::io::{Read, Write}; + use ylong_http::body::sync_impl::Body; use ylong_http::request::Request; use ylong_http::response::Response; +use crate::error::HttpClientError; +use crate::sync_impl::HttpBody; +use crate::util::dispatcher::Conn; + #[cfg(feature = "http1_1")] mod http1; diff --git a/ylong_http_client/src/sync_impl/connector.rs b/ylong_http_client/src/sync_impl/connector.rs index b16d4f0..b535975 100644 --- a/ylong_http_client/src/sync_impl/connector.rs +++ b/ylong_http_client/src/sync_impl/connector.rs @@ -11,10 +11,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::util::ConnectorConfig; use std::io::{Read, Write}; + use ylong_http::request::uri::Uri; +use crate::util::ConnectorConfig; + /// `Connector` trait used by `Client`. `Connector` provides synchronous /// connection establishment interfaces. pub trait Connector { @@ -49,11 +51,13 @@ impl Default for HttpConnector { #[cfg(not(feature = "__tls"))] pub mod no_tls { - use crate::sync_impl::Connector; use std::io::Error; use std::net::TcpStream; + use ylong_http::request::uri::Uri; + use crate::sync_impl::Connector; + impl Connector for super::HttpConnector { type Stream = TcpStream; type Error = Error; @@ -71,16 +75,14 @@ pub mod no_tls { #[cfg(feature = "__tls")] pub mod tls_conn { - use crate::{ - sync_impl::{Connector, MixStream}, - ErrorKind, HttpClientError, - }; - use std::{ - io::{Read, Write}, - net::TcpStream, - }; + use std::io::{Read, Write}; + use std::net::TcpStream; + use ylong_http::request::uri::{Scheme, Uri}; + use crate::sync_impl::{Connector, MixStream}; + use crate::{ErrorKind, HttpClientError}; + impl Connector for super::HttpConnector { type Stream = MixStream; type Error = HttpClientError; diff --git a/ylong_http_client/src/sync_impl/http_body.rs b/ylong_http_client/src/sync_impl/http_body.rs index f0ab1a3..c5cad03 100644 --- a/ylong_http_client/src/sync_impl/http_body.rs +++ b/ylong_http_client/src/sync_impl/http_body.rs @@ -11,12 +11,14 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::io::{Cursor, Read}; + +use ylong_http::body::{ChunkBodyDecoder, ChunkState, TextBodyDecoder}; +use ylong_http::headers::{HeaderName, HeaderValue, Headers}; + use super::Body; use crate::error::{ErrorKind, HttpClientError}; use crate::sync_impl::conn::StreamData; -use std::io::{Cursor, Read}; -use ylong_http::body::{ChunkBodyDecoder, ChunkState, TextBodyDecoder}; -use ylong_http::headers::{HeaderName, HeaderValue, Headers}; /// `HttpBody` is the body part of the `Response` returned by `Client::request`. /// `HttpBody` implements `Body` trait, so users can call related methods to get @@ -25,8 +27,8 @@ use ylong_http::headers::{HeaderName, HeaderValue, Headers}; /// # Examples /// /// ```no_run -/// use ylong_http_client::sync_impl::{Client, HttpBody, Body}; -/// use ylong_http_client::{Request, EmptyBody}; +/// use ylong_http_client::sync_impl::{Body, Client, HttpBody}; +/// use ylong_http_client::{EmptyBody, Request}; /// /// let mut client = Client::new(); /// @@ -389,9 +391,10 @@ impl Chunk { #[cfg(test)] mod ut_syn_http_body { + use ylong_http::body::ChunkBodyDecoder; + use crate::sync_impl::http_body::Chunk; use crate::sync_impl::{Body, HttpBody}; - use ylong_http::body::ChunkBodyDecoder; /// UT test cases for `HttpBody::empty`. /// diff --git a/ylong_http_client/src/sync_impl/mod.rs b/ylong_http_client/src/sync_impl/mod.rs index acc7a9f..f63e836 100644 --- a/ylong_http_client/src/sync_impl/mod.rs +++ b/ylong_http_client/src/sync_impl/mod.rs @@ -34,15 +34,13 @@ mod reader; pub use client::{Client, ClientBuilder}; pub use connector::Connector; +pub(crate) use connector::HttpConnector; pub use http_body::HttpBody; pub use reader::{BodyProcessError, BodyProcessor, BodyReader, DefaultBodyProcessor}; pub use ylong_http::body::sync_impl::Body; - // TODO: Adapter, remove this later. pub use ylong_http::response::Response; -pub(crate) use connector::HttpConnector; - #[cfg(feature = "__tls")] mod ssl_stream; #[cfg(feature = "__tls")] diff --git a/ylong_http_client/src/sync_impl/pool.rs b/ylong_http_client/src/sync_impl/pool.rs index be6dac4..afd2f53 100644 --- a/ylong_http_client/src/sync_impl/pool.rs +++ b/ylong_http_client/src/sync_impl/pool.rs @@ -11,15 +11,16 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::error::Error; +use std::io::{Read, Write}; +use std::mem::take; +use std::sync::{Arc, Mutex}; + use crate::error::{ErrorKind, HttpClientError}; use crate::sync_impl::Connector; use crate::util::dispatcher::{Conn, ConnDispatcher, Dispatcher}; use crate::util::pool::{Pool, PoolKey}; use crate::Uri; -use std::error::Error; -use std::io::{Read, Write}; -use std::mem::take; -use std::sync::{Arc, Mutex}; pub(crate) struct ConnPool { pool: Pool>, diff --git a/ylong_http_client/src/sync_impl/reader.rs b/ylong_http_client/src/sync_impl/reader.rs index a879bc5..1dbd24c 100644 --- a/ylong_http_client/src/sync_impl/reader.rs +++ b/ylong_http_client/src/sync_impl/reader.rs @@ -11,13 +11,14 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::error::Error; +use std::fmt::{Debug, Display, Formatter}; +use std::time::{Duration, Instant}; + use super::Body; use crate::error::HttpClientError; use crate::util::Timeout; use crate::ErrorKind; -use std::error::Error; -use std::fmt::{Debug, Display, Formatter}; -use std::time::{Duration, Instant}; /// A reader used to read all the body data to a specified location and provide /// echo function. @@ -25,7 +26,7 @@ use std::time::{Duration, Instant}; /// # Examples /// /// ``` -/// use ylong_http_client::sync_impl::{BodyReader, BodyProcessor, BodyProcessError}; +/// use ylong_http_client::sync_impl::{BodyProcessError, BodyProcessor, BodyReader}; /// use ylong_http_client::TextBody; /// /// // Defines a processor, which provides read and echo ability. @@ -49,7 +50,10 @@ use std::time::{Duration, Instant}; /// } /// /// let mut body = TextBody::from_bytes(b"HelloWorld"); -/// let mut processor = Processor { vec: Vec::new(), echo: 0 }; +/// let mut processor = Processor { +/// vec: Vec::new(), +/// echo: 0, +/// }; /// let _ = BodyReader::new(&mut processor).read_all(&mut body); /// /// // All data is read. @@ -87,16 +91,16 @@ impl BodyReader { /// use ylong_http_client::sync_impl::{BodyReader, DefaultBodyProcessor}; /// use ylong_http_client::util::Timeout; /// - /// let reader = BodyReader::new(DefaultBodyProcessor::new()) - /// .read_timeout(Timeout::none()); + /// let reader = BodyReader::new(DefaultBodyProcessor::new()).read_timeout(Timeout::none()); /// ``` pub fn read_timeout(mut self, timeout: Timeout) -> Self { self.read_timeout = timeout; self } - /// Reads all the body data. During the read process, [`BodyProcessor::write`] and - /// [`BodyProcessor::progress`] will be called multiple times. + /// Reads all the body data. During the read process, + /// [`BodyProcessor::write`] and [`BodyProcessor::progress`] will be + /// called multiple times. /// /// [`BodyProcessor::write`]: BodyProcessor::write /// [`BodyProcessor::progress`]: BodyProcessor::progress @@ -104,7 +108,7 @@ impl BodyReader { /// # Examples /// /// ``` - /// use ylong_http_client::sync_impl::{BodyReader, BodyProcessor}; + /// use ylong_http_client::sync_impl::{BodyProcessor, BodyReader}; /// use ylong_http_client::TextBody; /// /// let mut body = TextBody::from_bytes(b"HelloWorld"); @@ -154,7 +158,8 @@ impl Default for BodyReader { } } -/// The trait defines methods for processing bodies of HTTP messages. Unlike the async version, this is for synchronous usage. +/// The trait defines methods for processing bodies of HTTP messages. Unlike the +/// async version, this is for synchronous usage. pub trait BodyProcessor { /// Writes the body data read each time to the specified location. /// @@ -217,14 +222,16 @@ impl Default for DefaultBodyProcessor { #[cfg(test)] mod ut_syn_reader { + use ylong_http::body::TextBody; + use crate::sync_impl::{BodyReader, DefaultBodyProcessor}; use crate::util::Timeout; - use ylong_http::body::TextBody; /// UT test cases for `BodyReader::read_timeout`. /// /// # Brief - /// 1. Creates a `BodyReader` with `DefaultBodyProcessor::default` by calling `BodyReader::new`. + /// 1. Creates a `BodyReader` with `DefaultBodyProcessor::default` by + /// calling `BodyReader::new`. /// 2. Calls `read_timeout`. /// 3. Checks if the result is correct. #[test] diff --git a/ylong_http_client/src/sync_impl/ssl_stream.rs b/ylong_http_client/src/sync_impl/ssl_stream.rs index 4917956..2a3e3c3 100644 --- a/ylong_http_client/src/sync_impl/ssl_stream.rs +++ b/ylong_http_client/src/sync_impl/ssl_stream.rs @@ -11,9 +11,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::io::{Read, Write}; + #[cfg(feature = "__c_openssl")] use crate::util::c_openssl::ssl::SslStream; -use std::io::{Read, Write}; /// A stream which may be wrapped with TLS. pub enum MixStream { diff --git a/ylong_http_client/src/util/base64.rs b/ylong_http_client/src/util/base64.rs index f33ae31..ef6e182 100644 --- a/ylong_http_client/src/util/base64.rs +++ b/ylong_http_client/src/util/base64.rs @@ -36,7 +36,7 @@ pub(crate) fn encode(input: &[u8]) -> Vec { } static BASE64_TABLE: [u8; 64] = [ - //0 1 2 3 4 5 6 7 + // 0 1 2 3 4 5 6 7 b'A', b'B', b'C', b'D', b'E', b'F', b'G', b'H', // 0 b'I', b'J', b'K', b'L', b'M', b'N', b'O', b'P', // 1 b'Q', b'R', b'S', b'T', b'U', b'V', b'W', b'X', // 2 @@ -54,7 +54,8 @@ mod ut_util_base64 { /// UT test cases for `base64::encode`. /// /// # Brief - /// 1. Calls `encode` to parse the string and convert it into `base64` format. + /// 1. Calls `encode` to parse the string and convert it into `base64` + /// format. /// 2. Checks if the results are correct. #[test] fn ut_util_base64_encode() { diff --git a/ylong_http_client/src/util/c_openssl/adapter.rs b/ylong_http_client/src/util/c_openssl/adapter.rs index 00b50b4..6914a03 100644 --- a/ylong_http_client/src/util/c_openssl/adapter.rs +++ b/ylong_http_client/src/util/c_openssl/adapter.rs @@ -11,16 +11,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{error::HttpClientError, util::AlpnProtocolList}; -use crate::{ - util::c_openssl::{ - error::ErrorStack, - ssl::{Ssl, SslContext, SslContextBuilder, SslFiletype, SslMethod, SslVersion}, - x509::{X509Ref, X509Store, X509}, - }, - ErrorKind, +use std::net::IpAddr; +use std::path::Path; + +use crate::error::HttpClientError; +use crate::util::c_openssl::error::ErrorStack; +use crate::util::c_openssl::ssl::{ + Ssl, SslContext, SslContextBuilder, SslFiletype, SslMethod, SslVersion, }; -use std::{net::IpAddr, path::Path}; +use crate::util::c_openssl::x509::{X509Ref, X509Store, X509}; +use crate::util::AlpnProtocolList; +use crate::ErrorKind; /// `TlsContextBuilder` implementation based on `SSL_CTX`. /// @@ -68,8 +69,7 @@ impl TlsConfigBuilder { /// ``` /// use ylong_http_client::util::TlsConfigBuilder; /// - /// let builder = TlsConfigBuilder::new() - /// .ca_file("ca.crt"); + /// let builder = TlsConfigBuilder::new().ca_file("ca.crt"); /// ``` pub fn ca_file>(mut self, path: T) -> Self { self.inner = self @@ -79,7 +79,8 @@ impl TlsConfigBuilder { } /// Sets the maximum supported protocol version. A value of `None` will - /// enable protocol versions down the the highest version supported by `OpenSSL`. + /// enable protocol versions down the the highest version supported by + /// `OpenSSL`. /// /// Requires `OpenSSL 1.1.0` or or `LibreSSL 2.6.1` or newer. /// @@ -88,8 +89,7 @@ impl TlsConfigBuilder { /// ``` /// use ylong_http_client::util::{TlsConfigBuilder, TlsVersion}; /// - /// let builder = TlsConfigBuilder::new() - /// .max_proto_version(TlsVersion::TLS_1_2); + /// let builder = TlsConfigBuilder::new().max_proto_version(TlsVersion::TLS_1_2); /// ``` pub fn max_proto_version(mut self, version: TlsVersion) -> Self { self.inner = self.inner.and_then(|mut builder| { @@ -101,7 +101,8 @@ impl TlsConfigBuilder { } /// Sets the minimum supported protocol version. A value of `None` will - /// enable protocol versions down the the lowest version supported by `OpenSSL`. + /// enable protocol versions down the the lowest version supported by + /// `OpenSSL`. /// /// Requires `OpenSSL 1.1.0` or `LibreSSL 2.6.1` or newer. /// @@ -110,8 +111,7 @@ impl TlsConfigBuilder { /// ``` /// use ylong_http_client::util::{TlsConfigBuilder, TlsVersion}; /// - /// let builder = TlsConfigBuilder::new() - /// .min_proto_version(TlsVersion::TLS_1_2); + /// let builder = TlsConfigBuilder::new().min_proto_version(TlsVersion::TLS_1_2); /// ``` pub fn min_proto_version(mut self, version: TlsVersion) -> Self { self.inner = self.inner.and_then(|mut builder| { @@ -136,9 +136,7 @@ impl TlsConfigBuilder { /// use ylong_http_client::util::TlsConfigBuilder; /// /// let builder = TlsConfigBuilder::new() - /// .cipher_list( - /// "DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK" - /// ); + /// .cipher_list("DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK"); /// ``` pub fn cipher_list(mut self, list: &str) -> Self { self.inner = self @@ -163,9 +161,7 @@ impl TlsConfigBuilder { /// use ylong_http_client::util::TlsConfigBuilder; /// /// let builder = TlsConfigBuilder::new() - /// .cipher_suites( - /// "DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK" - /// ); + /// .cipher_suites("DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK"); /// ``` pub fn cipher_suites(mut self, list: &str) -> Self { self.inner = self @@ -177,16 +173,16 @@ impl TlsConfigBuilder { /// Loads a leaf certificate from a file. /// /// Only a single certificate will be loaded - use `add_extra_chain_cert` to - /// add the remainder of the certificate chain, or `set_certificate_chain_file` - /// to load the entire chain from a single file. + /// add the remainder of the certificate chain, or + /// `set_certificate_chain_file` to load the entire chain from a single + /// file. /// /// # Examples /// /// ``` /// use ylong_http_client::util::{TlsConfigBuilder, TlsFileType}; /// - /// let builder = TlsConfigBuilder::new() - /// .certificate_file("cert.pem", TlsFileType::PEM); + /// let builder = TlsConfigBuilder::new().certificate_file("cert.pem", TlsFileType::PEM); /// ``` pub fn certificate_file>(mut self, path: T, file_type: TlsFileType) -> Self { self.inner = self.inner.and_then(|mut builder| { @@ -228,13 +224,14 @@ impl TlsConfigBuilder { self } - /// Sets the protocols to sent to the server for Application Layer Protocol Negotiation (ALPN). + /// Sets the protocols to sent to the server for Application Layer Protocol + /// Negotiation (ALPN). /// /// Requires OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer. /// /// # Examples /// ``` - /// use ylong_http_client::util::{TlsConfigBuilder}; + /// use ylong_http_client::util::TlsConfigBuilder; /// /// let protocols = b"\x06spdy/1\x08http/1.1"; /// let builder = TlsConfigBuilder::new().alpn_protos(protocols); @@ -246,7 +243,8 @@ impl TlsConfigBuilder { self } - /// Sets the protocols to sent to the server for Application Layer Protocol Negotiation (ALPN). + /// Sets the protocols to sent to the server for Application Layer Protocol + /// Negotiation (ALPN). /// /// This method is based on `openssl::SslContextBuilder::set_alpn_protos`. /// @@ -268,8 +266,8 @@ impl TlsConfigBuilder { self } - /// Controls the use of built-in system certificates during certificate validation. - /// Default to `true` -- uses built-in system certs. + /// Controls the use of built-in system certificates during certificate + /// validation. Default to `true` -- uses built-in system certs. pub fn build_in_root_certs(mut self, is_use: bool) -> Self { if !is_use { self.inner = X509Store::new().and_then(|store| { @@ -350,7 +348,8 @@ impl TlsConfigBuilder { self } - /// Builds a `TlsContext`. Returns `Err` if an error occurred during configuration. + /// Builds a `TlsContext`. Returns `Err` if an error occurred during + /// configuration. /// /// # Examples /// @@ -613,10 +612,8 @@ impl Certificate { #[cfg(test)] mod ut_openssl_adapter { - use crate::{ - util::{Cert, TlsConfigBuilder, TlsFileType, TlsVersion}, - AlpnProtocol, AlpnProtocolList, Certificate, - }; + use crate::util::{Cert, TlsConfigBuilder, TlsFileType, TlsVersion}; + use crate::{AlpnProtocol, AlpnProtocolList, Certificate}; /// UT test cases for `TlsConfigBuilder::new`. /// @@ -767,7 +764,8 @@ mod ut_openssl_adapter { /// UT test cases for `TlsConfig::ssl`. /// /// # Brief - /// 1. Creates a `TlsConfig` by calling `TlsConfigBuilder::new` and `TlsConfigBuilder::build`. + /// 1. Creates a `TlsConfig` by calling `TlsConfigBuilder::new` and + /// `TlsConfigBuilder::build`. /// 2. Creates a `TlsSsl` by calling `TlsConfig::ssl_new`. /// 3. Calls `TlsSsl::into_inner`. /// 4. Checks if the result is as expected. diff --git a/ylong_http_client/src/util/c_openssl/bio.rs b/ylong_http_client/src/util/c_openssl/bio.rs index be47d6c..7565af9 100644 --- a/ylong_http_client/src/util/c_openssl/bio.rs +++ b/ylong_http_client/src/util/c_openssl/bio.rs @@ -11,23 +11,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::{ - check_ptr, - error::ErrorStack, - ffi::bio::{ - BIO_clear_flags, BIO_free_all, BIO_get_data, BIO_meth_free, BIO_meth_new, - BIO_meth_set_create, BIO_meth_set_ctrl, BIO_meth_set_destroy, BIO_meth_set_puts, - BIO_meth_set_read, BIO_meth_set_write, BIO_new, BIO_new_mem_buf, BIO_set_data, - BIO_set_flags, BIO_set_init, BIO, BIO_METHOD, - }, - ssl_init, -}; -use core::{any::Any, marker::PhantomData, panic::AssertUnwindSafe, ptr, slice}; +use core::any::Any; +use core::marker::PhantomData; +use core::panic::AssertUnwindSafe; +use core::{ptr, slice}; +use std::io::{self, Read, Write}; +use std::panic::catch_unwind; + use libc::{c_char, c_int, c_long, c_void, strlen}; -use std::{ - io::{self, Read, Write}, - panic::catch_unwind, + +use super::error::ErrorStack; +use super::ffi::bio::{ + BIO_clear_flags, BIO_free_all, BIO_get_data, BIO_meth_free, BIO_meth_new, BIO_meth_set_create, + BIO_meth_set_ctrl, BIO_meth_set_destroy, BIO_meth_set_puts, BIO_meth_set_read, + BIO_meth_set_write, BIO_new, BIO_new_mem_buf, BIO_set_data, BIO_set_flags, BIO_set_init, BIO, + BIO_METHOD, }; +use super::{check_ptr, ssl_init}; #[derive(Debug)] pub struct Bio(*mut BIO); diff --git a/ylong_http_client/src/util/c_openssl/error.rs b/ylong_http_client/src/util/c_openssl/error.rs index 324ad62..9410d26 100644 --- a/ylong_http_client/src/util/c_openssl/error.rs +++ b/ylong_http_client/src/util/c_openssl/error.rs @@ -11,23 +11,24 @@ // See the License for the specific language governing permissions and // limitations under the License. +use core::ffi::CStr; +use core::{ptr, str}; +use std::borrow::Cow; +use std::error::Error; +#[cfg(feature = "c_openssl_3_0")] +use std::ffi::CString; +use std::fmt; + +#[cfg(feature = "c_openssl_1_1")] +use libc::c_char; +use libc::{c_int, c_ulong}; + use super::ssl_init; #[cfg(feature = "c_openssl_3_0")] use crate::util::c_openssl::ffi::err::ERR_get_error_all; #[cfg(feature = "c_openssl_1_1")] use crate::util::c_openssl::ffi::err::{ERR_func_error_string, ERR_get_error_line_data}; - use crate::util::c_openssl::ffi::err::{ERR_lib_error_string, ERR_reason_error_string}; -use core::{ffi::CStr, ptr, str}; - -#[cfg(feature = "c_openssl_1_1")] -use libc::c_char; -#[cfg(feature = "c_openssl_3_0")] -use std::ffi::CString; - -use libc::{c_int, c_ulong}; - -use std::{borrow::Cow, error::Error, fmt}; const ERR_TXT_MALLOCED: c_int = 0x01; const ERR_TXT_STRING: c_int = 0x02; diff --git a/ylong_http_client/src/util/c_openssl/ffi/bio.rs b/ylong_http_client/src/util/c_openssl/ffi/bio.rs index 6fd13e9..62ad6c7 100644 --- a/ylong_http_client/src/util/c_openssl/ffi/bio.rs +++ b/ylong_http_client/src/util/c_openssl/ffi/bio.rs @@ -17,8 +17,9 @@ pub(crate) enum BIO {} // for `BIO` extern "C" { - /// Creates a memory BIO using len bytes of data at buf, if len is -1 then the - /// buf is assumed to be nul terminated and its length is determined by strlen. + /// Creates a memory BIO using len bytes of data at buf, if len is -1 then + /// the buf is assumed to be nul terminated and its length is determined + /// by strlen. pub(crate) fn BIO_new_mem_buf(buf: *const c_void, len: c_int) -> *mut BIO; pub(crate) fn BIO_set_data(a: *mut BIO, data: *mut c_void); diff --git a/ylong_http_client/src/util/c_openssl/ffi/err.rs b/ylong_http_client/src/util/c_openssl/ffi/err.rs index e9dab63..093ae08 100644 --- a/ylong_http_client/src/util/c_openssl/ffi/err.rs +++ b/ylong_http_client/src/util/c_openssl/ffi/err.rs @@ -25,9 +25,9 @@ extern "C" { pub(crate) fn ERR_clear_error(); - /// Returns the earliest error code from the thread's error queue and removes - /// the entry. This function can be called repeatedly until there are no more - /// error codes to return. + /// Returns the earliest error code from the thread's error queue and + /// removes the entry. This function can be called repeatedly until + /// there are no more error codes to return. #[cfg(feature = "c_openssl_3_0")] pub(crate) fn ERR_get_error_all( file: *mut *const c_char, diff --git a/ylong_http_client/src/util/c_openssl/ffi/mod.rs b/ylong_http_client/src/util/c_openssl/ffi/mod.rs index e729ed2..e24ca13 100644 --- a/ylong_http_client/src/util/c_openssl/ffi/mod.rs +++ b/ylong_http_client/src/util/c_openssl/ffi/mod.rs @@ -25,6 +25,7 @@ use libc::c_int; pub(crate) enum OPENSSL_INIT_SETTINGS {} extern "C" { - /// Calls this function will explicitly initialise BOTH libcrypto and libssl. + /// Calls this function will explicitly initialise BOTH libcrypto and + /// libssl. pub(crate) fn OPENSSL_init_ssl(opts: u64, settings: *const OPENSSL_INIT_SETTINGS) -> c_int; } diff --git a/ylong_http_client/src/util/c_openssl/ffi/pem.rs b/ylong_http_client/src/util/c_openssl/ffi/pem.rs index b050508..cc94347 100644 --- a/ylong_http_client/src/util/c_openssl/ffi/pem.rs +++ b/ylong_http_client/src/util/c_openssl/ffi/pem.rs @@ -11,9 +11,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::{bio::BIO, x509::C_X509}; use libc::{c_char, c_int, c_void}; +use super::bio::BIO; +use super::x509::C_X509; + // callback func pub(crate) type PemPasswordCb = Option< unsafe extern "C" fn( diff --git a/ylong_http_client/src/util/c_openssl/ffi/ssl.rs b/ylong_http_client/src/util/c_openssl/ffi/ssl.rs index c614044..5fa2d8e 100644 --- a/ylong_http_client/src/util/c_openssl/ffi/ssl.rs +++ b/ylong_http_client/src/util/c_openssl/ffi/ssl.rs @@ -11,12 +11,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::{ - bio::BIO, - x509::{C_X509, X509_STORE, X509_STORE_CTX, X509_VERIFY_PARAM}, -}; use libc::{c_char, c_int, c_long, c_uchar, c_uint, c_void}; +use super::bio::BIO; +use super::x509::{C_X509, X509_STORE, X509_STORE_CTX, X509_VERIFY_PARAM}; + /// This is the global context structure which is created by a server or client /// once per program life-time and which holds mainly default values for the /// `SSL` structures which are later created for the connections. @@ -68,10 +67,11 @@ extern "C" { file_type: c_int, ) -> c_int; - /// Loads a certificate chain from file into ctx. The certificates must be in - /// PEM format and must be sorted starting with the subject's certificate (actual - /// client or server certificate), followed by intermediate CA certificates - /// if applicable, and ending at the highest level (root) CA. + /// Loads a certificate chain from file into ctx. The certificates must be + /// in PEM format and must be sorted starting with the subject's + /// certificate (actual client or server certificate), followed by + /// intermediate CA certificates if applicable, and ending at the + /// highest level (root) CA. pub(crate) fn SSL_CTX_use_certificate_chain_file( ctx: *mut SSL_CTX, cert_chain_file: *const c_char, @@ -85,25 +85,28 @@ extern "C" { ) -> c_int; /// Sets/replaces the certificate verification storage of ctx to/with store. - /// If another X509_STORE object is currently set in ctx, it will be X509_STORE_free()ed. + /// If another X509_STORE object is currently set in ctx, it will be + /// X509_STORE_free()ed. pub(crate) fn SSL_CTX_set_cert_store(ctx: *mut SSL_CTX, store: *mut X509_STORE); /// Returns a pointer to the current certificate verification storage. pub(crate) fn SSL_CTX_get_cert_store(ctx: *const SSL_CTX) -> *mut X509_STORE; - /// Specifies that the default locations from which CA certificates are loaded - /// should be used. There is one default directory, one default file and one - /// default store. The default CA certificates directory is called certs in the - /// default OpenSSL directory, and this is also the default store. - /// Alternatively the SSL_CERT_DIR environment variable can be defined to - /// override this location. The default CA certificates file is called cert.pem - /// in the default OpenSSL directory. Alternatively the SSL_CERT_FILE environment - /// variable can be defined to override this location. + /// Specifies that the default locations from which CA certificates are + /// loaded should be used. There is one default directory, one default + /// file and one default store. The default CA certificates directory is + /// called certs in the default OpenSSL directory, and this is also the + /// default store. Alternatively the SSL_CERT_DIR environment variable + /// can be defined to override this location. The default CA + /// certificates file is called cert.pem in the default OpenSSL + /// directory. Alternatively the SSL_CERT_FILE environment variable can + /// be defined to override this location. pub(crate) fn SSL_CTX_set_default_verify_paths(ctx: *mut SSL_CTX) -> c_int; - /// Sets the verification flags for ctx to be mode and specifies the verify_callback - /// function to be used. - /// If no callback function shall be specified, the NULL pointer can be use for verify_callback. + /// Sets the verification flags for ctx to be mode and specifies the + /// verify_callback function to be used. + /// If no callback function shall be specified, the NULL pointer can be use + /// for verify_callback. pub(crate) fn SSL_CTX_set_verify( ctx: *mut SSL_CTX, mode: c_int, @@ -112,10 +115,10 @@ extern "C" { } -/// This is the main SSL/TLS structure which is created by a server or client per -/// established connection. This actually is the core structure in the SSL API. -/// At run-time the application usually deals with this structure which has links -/// to mostly all other structures. +/// This is the main SSL/TLS structure which is created by a server or client +/// per established connection. This actually is the core structure in the SSL +/// API. At run-time the application usually deals with this structure which has +/// links to mostly all other structures. pub(crate) enum SSL {} // for `SSL` @@ -128,14 +131,17 @@ extern "C" { pub(crate) fn SSL_free(ssl: *mut SSL); /// Obtains result code for TLS/SSL I/O operation.\ - /// SSL_get_error() must be used in the same thread that performed the TLS/SSL - /// I/O operation, and no other OpenSSL function calls should appear in between. + /// SSL_get_error() must be used in the same thread that performed the + /// TLS/SSL I/O operation, and no other OpenSSL function calls should + /// appear in between. pub(crate) fn SSL_get_error(ssl: *const SSL, ret: c_int) -> c_int; - /// Returns an abbreviated string indicating the current state of the SSL object ssl. + /// Returns an abbreviated string indicating the current state of the SSL + /// object ssl. pub(crate) fn SSL_state_string_long(ssl: *const SSL) -> *const c_char; - /// Returns the result of the verification of the X509 certificate presented by the peer, if any. + /// Returns the result of the verification of the X509 certificate presented + /// by the peer, if any. pub(crate) fn SSL_get_verify_result(ssl: *const SSL) -> c_long; pub(crate) fn SSL_set_bio(ssl: *mut SSL, rbio: *mut BIO, wbio: *mut BIO); @@ -152,20 +158,21 @@ extern "C" { pub(crate) fn SSL_ctrl(ssl: *mut SSL, cmd: c_int, larg: c_long, parg: *mut c_void) -> c_long; - /// Retrieve an internal pointer to the verification parameters for ssl respectively. - /// The returned pointer must not be freed by the calling application. + /// Retrieve an internal pointer to the verification parameters for ssl + /// respectively. The returned pointer must not be freed by the calling + /// application. pub(crate) fn SSL_get0_param(ssl: *mut SSL) -> *mut X509_VERIFY_PARAM; } -/// This is a dispatch structure describing the internal ssl library methods/functions -/// which implement the various protocol versions (SSLv3 TLSv1, ...). -/// It's needed to create an `SSL_CTX`. +/// This is a dispatch structure describing the internal ssl library +/// methods/functions which implement the various protocol versions (SSLv3 +/// TLSv1, ...). It's needed to create an `SSL_CTX`. pub(crate) enum SSL_METHOD {} // for `SSL_METHOD` extern "C" { - /// Is the general-purpose version-flexible SSL/TLS methods. The actual protocol - /// version used will be negotiated to the highest version mutually supported - /// by the client and the server. + /// Is the general-purpose version-flexible SSL/TLS methods. The actual + /// protocol version used will be negotiated to the highest version + /// mutually supported by the client and the server. pub(crate) fn TLS_client_method() -> *const SSL_METHOD; } diff --git a/ylong_http_client/src/util/c_openssl/mod.rs b/ylong_http_client/src/util/c_openssl/mod.rs index 5892ea7..785a981 100644 --- a/ylong_http_client/src/util/c_openssl/mod.rs +++ b/ylong_http_client/src/util/c_openssl/mod.rs @@ -26,15 +26,17 @@ pub(crate) mod stack; pub(crate) mod x509; pub mod adapter; -pub use adapter::{Cert, Certificate, TlsConfig, TlsConfigBuilder, TlsFileType, TlsVersion}; - -use crate::util::c_openssl::ffi::OPENSSL_init_ssl; use core::ptr; -use error::ErrorStack; -use libc::c_int; use std::sync::Once; -/// Automatic loading of the libssl error strings. This option is a default option. +pub use adapter::{Cert, Certificate, TlsConfig, TlsConfigBuilder, TlsFileType, TlsVersion}; +use error::ErrorStack; +use libc::c_int; + +use crate::util::c_openssl::ffi::OPENSSL_init_ssl; + +/// Automatic loading of the libssl error strings. This option is a default +/// option. pub(crate) const OPENSSL_INIT_LOAD_SSL_STRINGS: u64 = 0x00200000; /// Checks null-pointer. diff --git a/ylong_http_client/src/util/c_openssl/ssl/ctx.rs b/ylong_http_client/src/util/c_openssl/ssl/ctx.rs index dd263ed..ae88e56 100644 --- a/ylong_http_client/src/util/c_openssl/ssl/ctx.rs +++ b/ylong_http_client/src/util/c_openssl/ssl/ctx.rs @@ -11,32 +11,28 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::{filetype::SslFiletype, method::SslMethod, version::SslVersion}; -use crate::{ - c_openssl::{ - ffi::ssl::{ - SSL_CTX_free, SSL_CTX_get_cert_store, SSL_CTX_set_default_verify_paths, - SSL_CTX_set_verify, - }, - x509::{X509Store, X509StoreRef}, - }, - util::c_openssl::{ - check_ptr, check_ret, - error::ErrorStack, - ffi::ssl::{ - SSL_CTX_ctrl, SSL_CTX_load_verify_locations, SSL_CTX_new, SSL_CTX_set_alpn_protos, - SSL_CTX_set_cert_store, SSL_CTX_set_cipher_list, SSL_CTX_set_ciphersuites, - SSL_CTX_up_ref, SSL_CTX_use_certificate_chain_file, SSL_CTX_use_certificate_file, - SSL_CTX, - }, - foreign::{Foreign, ForeignRef}, - ssl_init, - x509::{X509Ref, X509}, - }, -}; use core::{fmt, mem, ptr}; +use std::ffi::CString; +use std::path::Path; + use libc::{c_int, c_long, c_uint, c_void}; -use std::{ffi::CString, path::Path}; + +use super::filetype::SslFiletype; +use super::method::SslMethod; +use super::version::SslVersion; +use crate::c_openssl::ffi::ssl::{ + SSL_CTX_free, SSL_CTX_get_cert_store, SSL_CTX_set_default_verify_paths, SSL_CTX_set_verify, +}; +use crate::c_openssl::x509::{X509Store, X509StoreRef}; +use crate::util::c_openssl::error::ErrorStack; +use crate::util::c_openssl::ffi::ssl::{ + SSL_CTX_ctrl, SSL_CTX_load_verify_locations, SSL_CTX_new, SSL_CTX_set_alpn_protos, + SSL_CTX_set_cert_store, SSL_CTX_set_cipher_list, SSL_CTX_set_ciphersuites, SSL_CTX_up_ref, + SSL_CTX_use_certificate_chain_file, SSL_CTX_use_certificate_file, SSL_CTX, +}; +use crate::util::c_openssl::foreign::{Foreign, ForeignRef}; +use crate::util::c_openssl::x509::{X509Ref, X509}; +use crate::util::c_openssl::{check_ptr, check_ret, ssl_init}; const SSL_CTRL_EXTRA_CHAIN_CERT: c_int = 14; @@ -193,8 +189,9 @@ impl SslContextBuilder { /// Loads a leaf certificate from a file. /// - /// Only a single certificate will be loaded - use `add_extra_chain_cert` to add the remainder - /// of the certificate chain, or `set_certificate_chain_file` to load the entire chain from a + /// Only a single certificate will be loaded - use `add_extra_chain_cert` to + /// add the remainder of the certificate chain, or + /// `set_certificate_chain_file` to load the entire chain from a /// single file. pub(crate) fn set_certificate_file

( &mut self, @@ -222,9 +219,9 @@ impl SslContextBuilder { /// Loads a certificate chain from file into ctx. /// The certificates must be in PEM format and must be sorted starting with - /// the subject's certificate (actual client or server certificate), followed - /// by intermediate CA certificates if applicable, and ending at the highest - /// level (root) CA. + /// the subject's certificate (actual client or server certificate), + /// followed by intermediate CA certificates if applicable, and ending + /// at the highest level (root) CA. pub(crate) fn set_certificate_chain_file

(&mut self, file: P) -> Result<(), ErrorStack> where P: AsRef, @@ -243,7 +240,8 @@ impl SslContextBuilder { .map(|_| ()) } - /// Sets the protocols to sent to the server for Application Layer Protocol Negotiation (ALPN). + /// Sets the protocols to sent to the server for Application Layer Protocol + /// Negotiation (ALPN). pub(crate) fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> { assert!(protocols.len() <= c_uint::max_value() as usize); diff --git a/ylong_http_client/src/util/c_openssl/ssl/error.rs b/ylong_http_client/src/util/c_openssl/ssl/error.rs index 0676697..f291d5f 100644 --- a/ylong_http_client/src/util/c_openssl/ssl/error.rs +++ b/ylong_http_client/src/util/c_openssl/ssl/error.rs @@ -11,12 +11,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::c_openssl::error::ErrorStack; use core::fmt; +use std::error::Error; +use std::io; + use libc::c_int; -use std::{error::Error, io}; use super::MidHandshakeSslStream; +use crate::c_openssl::error::ErrorStack; #[derive(Debug)] pub(crate) struct SslError { diff --git a/ylong_http_client/src/util/c_openssl/ssl/ssl_base.rs b/ylong_http_client/src/util/c_openssl/ssl/ssl_base.rs index 5120500..f083062 100644 --- a/ylong_http_client/src/util/c_openssl/ssl/ssl_base.rs +++ b/ylong_http_client/src/util/c_openssl/ssl/ssl_base.rs @@ -11,33 +11,28 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::{error::HandshakeError, MidHandshakeSslStream, SslContext, SslErrorCode, SslStream}; -use crate::{ - c_openssl::{ - check_ret, - ffi::{ - bio::BIO, - ssl::{ - SSL_connect, SSL_ctrl, SSL_get0_param, SSL_get_error, SSL_get_rbio, - SSL_get_verify_result, SSL_read, SSL_state_string_long, SSL_write, - }, - }, - foreign::ForeignRef, - x509::{X509VerifyParamRef, X509VerifyResult, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS}, - }, - util::c_openssl::{ - check_ptr, - error::ErrorStack, - ffi::ssl::{SSL_free, SSL_new, SSL}, - foreign::Foreign, - }, -}; use core::{cmp, ffi, fmt, str}; +use std::ffi::CString; +use std::io::{Read, Write}; + use libc::{c_char, c_int, c_long, c_void}; -use std::{ - ffi::CString, - io::{Read, Write}, + +use super::error::HandshakeError; +use super::{MidHandshakeSslStream, SslContext, SslErrorCode, SslStream}; +use crate::c_openssl::check_ret; +use crate::c_openssl::ffi::bio::BIO; +use crate::c_openssl::ffi::ssl::{ + SSL_connect, SSL_ctrl, SSL_get0_param, SSL_get_error, SSL_get_rbio, SSL_get_verify_result, + SSL_read, SSL_state_string_long, SSL_write, }; +use crate::c_openssl::foreign::ForeignRef; +use crate::c_openssl::x509::{ + X509VerifyParamRef, X509VerifyResult, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS, +}; +use crate::util::c_openssl::check_ptr; +use crate::util::c_openssl::error::ErrorStack; +use crate::util::c_openssl::ffi::ssl::{SSL_free, SSL_new, SSL}; +use crate::util::c_openssl::foreign::Foreign; foreign_type!( type CStruct = SSL; diff --git a/ylong_http_client/src/util/c_openssl/ssl/stream.rs b/ylong_http_client/src/util/c_openssl/ssl/stream.rs index ed99ce7..e9e4575 100644 --- a/ylong_http_client/src/util/c_openssl/ssl/stream.rs +++ b/ylong_http_client/src/util/c_openssl/ssl/stream.rs @@ -11,22 +11,20 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::{InternalError, Ssl, SslError, SslErrorCode, SslRef}; -use crate::{ - c_openssl::{ - bio::{self, get_error, get_panic, get_stream_mut, get_stream_ref}, - error::ErrorStack, - ffi::ssl::{SSL_connect, SSL_set_bio, SSL_shutdown}, - foreign::Foreign, - }, - util::c_openssl::bio::BioMethod, -}; -use core::{fmt, marker::PhantomData, mem::ManuallyDrop}; +use core::fmt; +use core::marker::PhantomData; +use core::mem::ManuallyDrop; +use std::io::{self, Read, Write}; +use std::panic::resume_unwind; + use libc::c_int; -use std::{ - io::{self, Read, Write}, - panic::resume_unwind, -}; + +use super::{InternalError, Ssl, SslError, SslErrorCode, SslRef}; +use crate::c_openssl::bio::{self, get_error, get_panic, get_stream_mut, get_stream_ref}; +use crate::c_openssl::error::ErrorStack; +use crate::c_openssl::ffi::ssl::{SSL_connect, SSL_set_bio, SSL_shutdown}; +use crate::c_openssl::foreign::Foreign; +use crate::util::c_openssl::bio::BioMethod; /// A TLS session over a stream. pub struct SslStream { @@ -175,7 +173,8 @@ impl Read for SslStream { // the close_notify alert. No more data can be read. // Does not necessarily indicate that the underlying transport has been closed. Err(ref e) if e.code == SslErrorCode::ZERO_RETURN => return Ok(0), - // A non-recoverable, fatal error in the SSL library occurred, usually a protocol error. + // A non-recoverable, fatal error in the SSL library occurred, usually a protocol + // error. Err(ref e) if e.code == SslErrorCode::SYSCALL && e.get_io_error().is_none() => { return Ok(0) } diff --git a/ylong_http_client/src/util/c_openssl/stack.rs b/ylong_http_client/src/util/c_openssl/stack.rs index f2c3d32..3f22216 100644 --- a/ylong_http_client/src/util/c_openssl/stack.rs +++ b/ylong_http_client/src/util/c_openssl/stack.rs @@ -11,18 +11,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::c_openssl::foreign::{Foreign, ForeignRef, ForeignRefWrapper}; -use core::{ - borrow::Borrow, - marker::PhantomData, - mem::forget, - ops::{Deref, DerefMut, Range}, -}; +use core::borrow::Borrow; +use core::marker::PhantomData; +use core::mem::forget; +use core::ops::{Deref, DerefMut, Range}; + use libc::c_int; use super::ffi::stack::{ OPENSSL_sk_free, OPENSSL_sk_num, OPENSSL_sk_pop, OPENSSL_sk_value, OPENSSL_STACK, }; +use crate::c_openssl::foreign::{Foreign, ForeignRef, ForeignRefWrapper}; pub(crate) trait Stackof: Foreign { type StackType; diff --git a/ylong_http_client/src/util/c_openssl/x509.rs b/ylong_http_client/src/util/c_openssl/x509.rs index 9d0fcfe..e962f7b 100644 --- a/ylong_http_client/src/util/c_openssl/x509.rs +++ b/ylong_http_client/src/util/c_openssl/x509.rs @@ -11,29 +11,25 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::{ - bio::BioSlice, - check_ptr, check_ret, - error::{error_get_lib, error_get_reason, ErrorStack}, - ffi::{ - err::{ERR_clear_error, ERR_peek_last_error}, - pem::PEM_read_bio_X509, - x509::{ - d2i_X509, X509_STORE_add_cert, X509_STORE_free, X509_STORE_new, X509_VERIFY_PARAM_free, - X509_VERIFY_PARAM_set1_host, X509_VERIFY_PARAM_set1_ip, - X509_VERIFY_PARAM_set_hostflags, X509_verify_cert_error_string, STACK_X509, X509_STORE, - X509_VERIFY_PARAM, - }, - }, - foreign::{Foreign, ForeignRef}, - ssl_init, - stack::Stackof, -}; -use crate::util::c_openssl::ffi::x509::{X509_free, C_X509}; use core::{ffi, fmt, ptr, str}; -use libc::{c_int, c_long, c_uint}; use std::net::IpAddr; +use libc::{c_int, c_long, c_uint}; + +use super::bio::BioSlice; +use super::error::{error_get_lib, error_get_reason, ErrorStack}; +use super::ffi::err::{ERR_clear_error, ERR_peek_last_error}; +use super::ffi::pem::PEM_read_bio_X509; +use super::ffi::x509::{ + d2i_X509, X509_STORE_add_cert, X509_STORE_free, X509_STORE_new, X509_VERIFY_PARAM_free, + X509_VERIFY_PARAM_set1_host, X509_VERIFY_PARAM_set1_ip, X509_VERIFY_PARAM_set_hostflags, + X509_verify_cert_error_string, STACK_X509, X509_STORE, X509_VERIFY_PARAM, +}; +use super::foreign::{Foreign, ForeignRef}; +use super::stack::Stackof; +use super::{check_ptr, check_ret, ssl_init}; +use crate::util::c_openssl::ffi::x509::{X509_free, C_X509}; + foreign_type!( type CStruct = C_X509; fn drop = X509_free; diff --git a/ylong_http_client/src/util/config/http.rs b/ylong_http_client/src/util/config/http.rs index 4be26c0..fd44598 100644 --- a/ylong_http_client/src/util/config/http.rs +++ b/ylong_http_client/src/util/config/http.rs @@ -65,9 +65,9 @@ pub(crate) mod http2 { /// use ylong_http_client::util::H2Config; /// /// let config = H2Config::new() - /// .set_header_table_size(4096) - /// .set_max_header_list_size(16 << 20) - /// .set_max_frame_size(2 << 13); + /// .set_header_table_size(4096) + /// .set_max_header_list_size(16 << 20) + /// .set_max_frame_size(2 << 13); /// ``` #[derive(Clone)] pub struct H2Config { @@ -97,8 +97,7 @@ pub(crate) mod http2 { /// ``` /// use ylong_http_client::util::H2Config; /// - /// let config = H2Config::new() - /// .set_max_frame_size(2 << 13); + /// let config = H2Config::new().set_max_frame_size(2 << 13); /// ``` pub fn set_max_frame_size(mut self, size: u32) -> Self { self.max_frame_size = size; @@ -112,8 +111,7 @@ pub(crate) mod http2 { /// ``` /// use ylong_http_client::util::H2Config; /// - /// let config = H2Config::new() - /// .set_max_header_list_size(16 << 20); + /// let config = H2Config::new().set_max_header_list_size(16 << 20); /// ``` pub fn set_max_header_list_size(mut self, size: u32) -> Self { self.max_header_list_size = size; @@ -127,8 +125,7 @@ pub(crate) mod http2 { /// ``` /// use ylong_http_client::util::H2Config; /// - /// let config = H2Config::new() - /// .set_max_header_list_size(4096); + /// let config = H2Config::new().set_max_header_list_size(4096); /// ``` pub fn set_header_table_size(mut self, size: u32) -> Self { self.header_table_size = size; @@ -142,8 +139,7 @@ pub(crate) mod http2 { /// ``` /// use ylong_http_client::util::H2Config; /// - /// let config = H2Config::new() - /// .set_max_frame_size(2 << 13); + /// let config = H2Config::new().set_max_frame_size(2 << 13); /// assert_eq!(config.max_frame_size(), 2 << 13); /// ``` pub fn max_frame_size(&self) -> u32 { @@ -157,8 +153,7 @@ pub(crate) mod http2 { /// ``` /// use ylong_http_client::util::H2Config; /// - /// let config = H2Config::new() - /// .set_max_header_list_size(16 << 20); + /// let config = H2Config::new().set_max_header_list_size(16 << 20); /// assert_eq!(config.max_header_list_size(), 16 << 20); /// ``` pub fn max_header_list_size(&self) -> u32 { @@ -172,8 +167,7 @@ pub(crate) mod http2 { /// ``` /// use ylong_http_client::util::H2Config; /// - /// let config = H2Config::new() - /// .set_header_table_size(4096); + /// let config = H2Config::new().set_header_table_size(4096); /// assert_eq!(config.header_table_size(), 4096); /// ``` pub fn header_table_size(&self) -> u32 { diff --git a/ylong_http_client/src/util/config/mod.rs b/ylong_http_client/src/util/config/mod.rs index 39fd83e..6cd5be3 100644 --- a/ylong_http_client/src/util/config/mod.rs +++ b/ylong_http_client/src/util/config/mod.rs @@ -19,16 +19,13 @@ mod settings; pub(crate) use client::ClientConfig; pub(crate) use connector::ConnectorConfig; pub(crate) use http::{HttpConfig, HttpVersion}; - pub use settings::{Proxy, ProxyBuilder, Redirect, Retry, SpeedLimit, Timeout}; #[cfg(feature = "__tls")] mod tls; -#[cfg(feature = "__tls")] -pub use tls::{AlpnProtocol, AlpnProtocolList}; - -#[cfg(feature = "tls_rust_ssl")] -pub use tls::{Certificate, PrivateKey, TlsConfig, TlsConfigBuilder, TlsFileType, TlsVersion}; - #[cfg(feature = "http2")] pub use http::http2::H2Config; +#[cfg(feature = "__tls")] +pub use tls::{AlpnProtocol, AlpnProtocolList}; +#[cfg(feature = "tls_rust_ssl")] +pub use tls::{Certificate, PrivateKey, TlsConfig, TlsConfigBuilder, TlsFileType, TlsVersion}; diff --git a/ylong_http_client/src/util/config/settings.rs b/ylong_http_client/src/util/config/settings.rs index 4452bd3..d1a7dde 100644 --- a/ylong_http_client/src/util/config/settings.rs +++ b/ylong_http_client/src/util/config/settings.rs @@ -11,17 +11,18 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::error::{ErrorKind, HttpClientError}; -use crate::util::proxy; -use crate::util::redirect as redirect_util; -use crate::util::redirect::{RedirectStrategy, TriggerKind}; use core::cmp; use core::time::Duration; + use ylong_http::request::uri::Uri; use ylong_http::request::Request; use ylong_http::response::status::StatusCode; use ylong_http::response::Response; +use crate::error::{ErrorKind, HttpClientError}; +use crate::util::redirect::{RedirectStrategy, TriggerKind}; +use crate::util::{proxy, redirect as redirect_util}; + /// Redirects settings of requests. /// /// # Example @@ -147,7 +148,8 @@ pub struct Retry(Option); impl Retry { const MAX_RETRIES: usize = 3; - /// Customizes the number of retries. Returns `Err` if `times` is greater than 3. + /// Customizes the number of retries. Returns `Err` if `times` is greater + /// than 3. /// /// # Examples /// @@ -296,7 +298,8 @@ impl SpeedLimit { /// Sets the minimum speed and the seconds for which the current speed is /// allowed to be less than this minimum speed. /// - /// The unit of speed is bytes per second, and the unit of duration is seconds. + /// The unit of speed is bytes per second, and the unit of duration is + /// seconds. /// /// The minimum speed cannot exceed the maximum speed that has been set. If /// the set value exceeds the currently set maximum speed, the minimum speed @@ -457,7 +460,8 @@ pub struct ProxyBuilder { } impl ProxyBuilder { - /// Pass HTTPS to the proxy URL, but the https uri which is in the no proxy list, will not pass the proxy URL. + /// Pass HTTPS to the proxy URL, but the https uri which is in the no proxy + /// list, will not pass the proxy URL. /// /// # Examples /// @@ -474,7 +478,8 @@ impl ProxyBuilder { self } - /// Pass HTTPS to the proxy URL, and set username and password which is required by the proxy server. + /// Pass HTTPS to the proxy URL, and set username and password which is + /// required by the proxy server. /// /// # Examples /// @@ -507,16 +512,17 @@ impl ProxyBuilder { #[cfg(test)] mod ut_settings { - use crate::error::HttpClientError; - use crate::util::redirect as redirect_util; - use crate::util::redirect::TriggerKind; - use crate::{Redirect, Retry}; use ylong_http::h1::ResponseDecoder; use ylong_http::request::uri::Uri; use ylong_http::request::Request; use ylong_http::response::status::StatusCode; use ylong_http::response::Response; + use crate::error::HttpClientError; + use crate::util::redirect as redirect_util; + use crate::util::redirect::TriggerKind; + use crate::{Redirect, Retry}; + fn create_trigger( redirect: &Redirect, previous: &[Uri], diff --git a/ylong_http_client/src/util/config/tls/alpn/mod.rs b/ylong_http_client/src/util/config/tls/alpn/mod.rs index 2cac5dc..cecefb4 100644 --- a/ylong_http_client/src/util/config/tls/alpn/mod.rs +++ b/ylong_http_client/src/util/config/tls/alpn/mod.rs @@ -11,8 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -/// TLS Application-Layer Protocol Negotiation (ALPN) Protocol is defined in [`RFC7301`]. -/// `AlpnProtocol` contains some protocols used in HTTP, which registered in [`IANA`]. +/// TLS Application-Layer Protocol Negotiation (ALPN) Protocol is defined in +/// [`RFC7301`]. `AlpnProtocol` contains some protocols used in HTTP, which +/// registered in [`IANA`]. /// /// [`RFC7301`]: https://www.rfc-editor.org/rfc/rfc7301.html#section-3 /// [`IANA`]: https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids @@ -87,7 +88,8 @@ impl AlpnProtocol { /// [`IANA Registration`]: https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids pub const H3: Self = Self(Inner::H3); - /// Gets ALPN “wire format”, which consists protocol name prefixed by its byte length. + /// Gets ALPN “wire format”, which consists protocol name prefixed by its + /// byte length. pub fn as_use_bytes(&self) -> &[u8] { match *self { AlpnProtocol::HTTP09 => b"\x08http/0.9", diff --git a/ylong_http_client/src/util/dispatcher.rs b/ylong_http_client/src/util/dispatcher.rs index 3a5a114..ceed59c 100644 --- a/ylong_http_client/src/util/dispatcher.rs +++ b/ylong_http_client/src/util/dispatcher.rs @@ -61,10 +61,11 @@ pub(crate) enum Conn { #[cfg(feature = "http1_1")] pub(crate) mod http1 { - use super::{ConnDispatcher, Dispatcher}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; + use super::{ConnDispatcher, Dispatcher}; + impl ConnDispatcher { pub(crate) fn http1(io: S) -> Self { Self::Http1(Http1Dispatcher::new(io)) @@ -144,15 +145,6 @@ pub(crate) mod http1 { #[cfg(feature = "http2")] pub(crate) mod http2 { - use super::{ConnDispatcher, Dispatcher}; - use crate::dispatcher::http2::StreamState::Closed; - use crate::error::HttpClientError; - use crate::util::H2Config; - use crate::ErrorKind; - use crate::MutexGuard; - use crate::TryRecvError; - use crate::{unbounded_channel, UnboundedReceiver, UnboundedSender}; - use crate::{AsyncMutex, AsyncRead, AsyncWrite, ReadBuf}; use std::collections::{HashMap, VecDeque}; use std::future::Future; use std::mem::take; @@ -160,6 +152,7 @@ pub(crate) mod http2 { use std::sync::atomic::{AtomicBool, AtomicU32, Ordering}; use std::sync::{Arc, Mutex}; use std::task::{Context, Poll, Waker}; + use ylong_http::error::HttpError; use ylong_http::h2; use ylong_http::h2::Payload::Settings; @@ -168,6 +161,15 @@ pub(crate) mod http2 { Goaway, H2Error, Payload, RstStream, Setting, SettingsBuilder, }; + use super::{ConnDispatcher, Dispatcher}; + use crate::dispatcher::http2::StreamState::Closed; + use crate::error::HttpClientError; + use crate::util::H2Config; + use crate::{ + unbounded_channel, AsyncMutex, AsyncRead, AsyncWrite, ErrorKind, MutexGuard, ReadBuf, + TryRecvError, UnboundedReceiver, UnboundedSender, + }; + impl ConnDispatcher { pub(crate) fn http2(config: H2Config, io: S) -> Self { Self::Http2(Http2Dispatcher::new(config, io)) @@ -208,9 +210,11 @@ pub(crate) mod http2 { } pub(crate) struct StreamController { - // I/O unavailability flag, which prevents the upper layer from using this I/O to create new streams. + // I/O unavailability flag, which prevents the upper layer from using this I/O to create + // new streams. pub(crate) io_shutdown: AtomicBool, - // Indicates that the dispatcher is occupied. At this time, a user coroutine is already acting as the dispatcher. + // Indicates that the dispatcher is occupied. At this time, a user coroutine is already + // acting as the dispatcher. pub(crate) occupied: AtomicU32, pub(crate) dispatcher_invalid: AtomicBool, pub(crate) manager: AsyncMutex>, @@ -389,7 +393,8 @@ pub(crate) mod http2 { } } - // TODO At present, only the state is changed to closed, and other states are not involved, and it needs to be added later + // TODO At present, only the state is changed to closed, and other states are + // not involved, and it needs to be added later pub(crate) fn recv_headers(&mut self, id: u32) -> Result { match self.buffer.get_mut(&id) { None => Err(H2Error::ConnectionError(ErrorCode::ProtocolError)), @@ -416,11 +421,13 @@ pub(crate) mod http2 { match self.stream_to_send.pop_front() { None => Ok(None), Some(id) => { - // TODO Subsequent consideration is to delete the corresponding elements in the map after the status becomes Closed + // TODO Subsequent consideration is to delete the corresponding elements in the + // map after the status becomes Closed match self.buffer.get_mut(&id) { None => Err(H2Error::ConnectionError(ErrorCode::IntervalError)), Some(sender) => { - // TODO For the time being, match state is used here, and the complete logic should be judged based on the frame type and state + // TODO For the time being, match state is used here, and the complete + // logic should be judged based on the frame type and state match sender.state { Closed(ResetReason::Remote | ResetReason::Local) => Ok(None), _ => Ok(sender.pop_front()), @@ -574,7 +581,8 @@ pub(crate) mod http2 { Some(handle) } - // TODO When the stream id reaches the maximum value, shutdown the current connection + // TODO When the stream id reaches the maximum value, shutdown the current + // connection fn is_shutdown(&self) -> bool { self.controller.io_shutdown.load(Ordering::Relaxed) } @@ -631,7 +639,8 @@ pub(crate) mod http2 { let stream_info = self.get_mut(); // First, check whether the frame of the current stream is in the Channel. - // The error cannot occur. Therefore, the error is thrown directly without connection-level processing. + // The error cannot occur. Therefore, the error is thrown directly without + // connection-level processing. if let Some(frame) = stream_info.receiver.recv_frame(stream_info.id)? { { let mut stream_waker = stream_info @@ -645,7 +654,8 @@ pub(crate) mod http2 { return Poll::Ready(Ok(frame)); } - // If the dispatcher sends a goaway frame, all streams on the current connection are unavailable. + // If the dispatcher sends a goaway frame, all streams on the current connection + // are unavailable. if stream_info .controller .dispatcher_invalid @@ -654,7 +664,8 @@ pub(crate) mod http2 { return Poll::Ready(Err(H2Error::ConnectionError(ErrorCode::ConnectError).into())); } - // The error cannot occur. Therefore, the error is thrown directly without connection-level processing. + // The error cannot occur. Therefore, the error is thrown directly without + // connection-level processing. if is_io_available(&stream_info.controller.occupied, stream_info.id)? { { // Second, try to get io and read the frame of the current stream from io. @@ -675,14 +686,16 @@ pub(crate) mod http2 { .expect("Blocking get waker lock failed! "); wakeup_next_stream(&mut stream_waker.waker); } - // The error cannot occur. Therefore, the error is thrown directly without connection-level processing. + // The error cannot occur. Therefore, the error is thrown directly without + // connection-level processing. let frame_opt = get_frame(stream_info.receiver.recv_frame(stream_info.id)?); return Poll::Ready(frame_opt); } { let mut io_manager = { - // Third, wait to acquire the lock of waker, which is used to insert the current waker, and wait to be awakened by the io stream. + // Third, wait to acquire the lock of waker, which is used to insert the current + // waker, and wait to be awakened by the io stream. let mut stream_waker = stream_info .controller .stream_waker @@ -690,17 +703,21 @@ pub(crate) mod http2 { .expect("Blocking get waker lock failed! "); // Fourth, after obtaining the waker lock, - // you need to check the Receiver again to prevent the Receiver from receiving a frame while waiting for the waker. - // The error cannot occur. Therefore, the error is thrown directly without connection-level processing. + // you need to check the Receiver again to prevent the Receiver from receiving a + // frame while waiting for the waker. The error cannot + // occur. Therefore, the error is thrown directly without connection-level + // processing. if let Some(frame) = stream_info.receiver.recv_frame(stream_info.id)? { wakeup_next_stream(&mut stream_waker.waker); return Poll::Ready(Ok(frame)); } - // The error cannot occur. Therefore, the error is thrown directly without connection-level processing. + // The error cannot occur. Therefore, the error is thrown directly without + // connection-level processing. if is_io_available(&stream_info.controller.occupied, stream_info.id)? { - // Fifth, get io again to prevent no other streams from controlling io while waiting for the waker, - // leaving only the current stream. + // Fifth, get io again to prevent no other streams from controlling io while + // waiting for the waker, leaving only the current + // stream. match stream_info.controller.manager.try_lock() { Ok(guard) => guard, _ => { @@ -733,7 +750,8 @@ pub(crate) mod http2 { .expect("Blocking get waker lock failed! "); wakeup_next_stream(&mut stream_waker.waker); } - // The error cannot occur. Therefore, the error is thrown directly without connection-level processing. + // The error cannot occur. Therefore, the error is thrown directly without + // connection-level processing. let frame_opt = get_frame(stream_info.receiver.recv_frame(stream_info.id)?); Poll::Ready(frame_opt) } @@ -782,7 +800,9 @@ pub(crate) mod http2 { .stream_waker .lock() .expect("Blocking get waker lock failed! "); - // TODO Is there a situation where the result has been returned, but the waker has not been inserted into the map? how to deal with. + // TODO Is there a situation where the result has been + // returned, but the waker has not been inserted into the + // map? how to deal with. if let Some(waker) = stream_waker.waker.remove(&id) { waker.wake(); } @@ -792,11 +812,15 @@ pub(crate) mod http2 { H2Error::ConnectionError(code) => { io_manager.close_frame_receiver(); self.controller.shutdown(); - // Since ConnectError may be caused by an io error, so when the client - // actively sends a goaway frame, all streams are shut down and no streams are allowed to complete. - // TODO Then consider separating io errors from frame errors to allow streams whose stream id is less than last_stream_id to continue + // Since ConnectError may be caused by an io error, so when the + // client actively sends a goaway + // frame, all streams are shut down and no streams are allowed to + // complete. TODO Then consider + // separating io errors from frame errors to allow streams whose + // stream id is less than last_stream_id to continue self.controller.invalid(); - // last_stream_id is set to 0 to ensure that all streams are shutdown. + // last_stream_id is set to 0 to ensure that all streams are + // shutdown. let goaway_payload = Goaway::new(code.clone().into_code(), 0, vec![]); let frame = Frame::new( @@ -852,7 +876,8 @@ pub(crate) mod http2 { return Poll::Pending; } } - // Write and read frames to io in a loop until the frame of the current stream is read and exit the loop. + // Write and read frames to io in a loop until the frame of the current stream + // is read and exit the loop. loop { if self.poll_write_frame(cx, io_manager)?.is_pending() { return Poll::Pending; @@ -971,11 +996,13 @@ pub(crate) mod http2 { ) -> Poll> { const FRAME_WRITE_NUM: usize = 10; - // Send 10 frames each time, if there is not enough in the queue, read enough from mpsc::Receiver + // Send 10 frames each time, if there is not enough in the queue, read enough + // from mpsc::Receiver while io_manager.streams.size() < FRAME_WRITE_NUM { match io_manager.frame_receiver.try_recv() { - // The Frame sent by the Handle for the first time will carry a Sender at the same time, - // which is used to send the Response Frame back to the Handle + // The Frame sent by the Handle for the first time will carry a Sender at the + // same time, which is used to send the Response Frame back + // to the Handle Ok((Some((id, sender)), frame)) => { if io_manager.senders.insert(id, sender).is_some() { return Poll::Ready(Err(H2Error::ConnectionError( @@ -1018,7 +1045,8 @@ pub(crate) mod http2 { cx: &mut Context<'_>, io_manager: &mut MutexGuard>, ) -> Poll> { - // Read all the frames in io until the frame of the current stream is read and stop. + // Read all the frames in io until the frame of the current stream is read and + // stop. let mut buf = [0u8; 1024]; loop { let mut read_buf = ReadBuf::new(&mut buf); @@ -1150,13 +1178,16 @@ pub(crate) mod http2 { break; } else { self.controller_send_frame_to_stream(stream_id, frame, io_manager); - // TODO After adding frames such as Reset/Priority, there may be problems with the following logic, because the lack of waker cannot wake up + // TODO After adding frames such as Reset/Priority, there may be + // problems with the following logic, because the lack of waker + // cannot wake up let mut stream_waker = self .controller .stream_waker .lock() .expect("Blocking get waker lock failed! "); - // TODO Is there a situation where the result has been returned, but the waker has not been inserted into the map? how to deal with. + // TODO Is there a situation where the result has been returned, but + // the waker has not been inserted into the map? how to deal with. if let Some(waker) = stream_waker.waker.remove(&stream_id) { waker.wake(); } @@ -1263,7 +1294,8 @@ pub(crate) mod http2 { ping: &h2::Ping, ) -> Poll> { if is_ack { - // TODO The sending logic of ping has not been implemented yet, so there is no processing for ack + // TODO The sending logic of ping has not been implemented yet, so there is no + // processing for ack Poll::Ready(Ok(())) } else { // reply ack Settings @@ -1283,7 +1315,8 @@ pub(crate) mod http2 { frame: Frame, guard: &mut MutexGuard>, ) { - // TODO Need to consider when to delete useless Sender after support reset stream + // TODO Need to consider when to delete useless Sender after support reset + // stream if let Some(sender) = guard.senders.get(&stream_id) { // If the client coroutine has exited, this frame is skipped. let _ = sender.send(frame); diff --git a/ylong_http_client/src/util/mod.rs b/ylong_http_client/src/util/mod.rs index 2f8c10d..0dd45fe 100644 --- a/ylong_http_client/src/util/mod.rs +++ b/ylong_http_client/src/util/mod.rs @@ -23,17 +23,15 @@ #![allow(unused_imports)] mod config; -pub(crate) use config::{ClientConfig, ConnectorConfig, HttpConfig, HttpVersion}; -pub use config::{Proxy, ProxyBuilder, Redirect, Retry, SpeedLimit, Timeout}; - #[cfg(feature = "__tls")] pub use config::{AlpnProtocol, AlpnProtocolList}; +pub(crate) use config::{ClientConfig, ConnectorConfig, HttpConfig, HttpVersion}; +pub use config::{Proxy, ProxyBuilder, Redirect, Retry, SpeedLimit, Timeout}; #[cfg(feature = "__c_openssl")] pub(crate) mod c_openssl; #[cfg(feature = "__c_openssl")] pub use c_openssl::{Cert, Certificate, TlsConfig, TlsConfigBuilder, TlsFileType, TlsVersion}; - #[cfg(feature = "http2")] pub use config::H2Config; diff --git a/ylong_http_client/src/util/normalizer.rs b/ylong_http_client/src/util/normalizer.rs index 11dc0e5..7af6f69 100644 --- a/ylong_http_client/src/util/normalizer.rs +++ b/ylong_http_client/src/util/normalizer.rs @@ -13,13 +13,14 @@ // TODO: Remove this file later. -use crate::{ErrorKind, HttpClientError, Uri}; use ylong_http::request::method::Method; use ylong_http::request::uri::Scheme; use ylong_http::request::Request; use ylong_http::response::status::StatusCode; use ylong_http::response::ResponsePart; +use crate::{ErrorKind, HttpClientError, Uri}; + pub(crate) struct RequestFormatter<'a, T> { part: &'a mut Request, } diff --git a/ylong_http_client/src/util/pool.rs b/ylong_http_client/src/util/pool.rs index 20f3f54..4d9aa56 100644 --- a/ylong_http_client/src/util/pool.rs +++ b/ylong_http_client/src/util/pool.rs @@ -17,6 +17,7 @@ use std::collections::hash_map::Entry; use std::collections::HashMap; use std::hash::Hash; use std::sync::{Arc, Mutex}; + use ylong_http::request::uri::{Authority, Scheme}; pub(crate) struct Pool { @@ -54,9 +55,11 @@ impl PoolKey { } #[cfg(test)] mod ut_pool { - use crate::pool::{Pool, PoolKey}; use std::sync::{Arc, Mutex}; + use ylong_http::request::uri::Uri; + + use crate::pool::{Pool, PoolKey}; /// UT test cases for `Pool::get`. /// /// # Brief diff --git a/ylong_http_client/src/util/proxy.rs b/ylong_http_client/src/util/proxy.rs index e455500..a35a694 100644 --- a/ylong_http_client/src/util/proxy.rs +++ b/ylong_http_client/src/util/proxy.rs @@ -13,14 +13,16 @@ //! Proxy implementation. +use core::convert::TryFrom; +use std::net::IpAddr; + +use ylong_http::headers::HeaderValue; +use ylong_http::request::uri::{Authority, Scheme, Uri}; + use crate::error::HttpClientError; use crate::util::base64::encode; use crate::util::normalizer::UriFormatter; use crate::ErrorKind; -use core::convert::TryFrom; -use std::net::IpAddr; -use ylong_http::headers::HeaderValue; -use ylong_http::request::uri::{Authority, Scheme, Uri}; /// `Proxies` is responsible for managing a list of proxies. #[derive(Clone, Default)] @@ -38,7 +40,8 @@ impl Proxies { } } -/// Proxy is a configuration of client which should manage the destination address of request. +/// Proxy is a configuration of client which should manage the destination +/// address of request. /// /// A `Proxy` has below rules: /// @@ -255,9 +258,10 @@ impl NoProxy { #[cfg(test)] mod ut_proxy { - use crate::util::proxy::{Proxies, Proxy}; use ylong_http::request::uri::{Scheme, Uri}; + use crate::util::proxy::{Proxies, Proxy}; + /// UT test cases for `Proxies`. /// /// # Brief diff --git a/ylong_http_client/src/util/redirect.rs b/ylong_http_client/src/util/redirect.rs index 4926e1b..3ca3c88 100644 --- a/ylong_http_client/src/util/redirect.rs +++ b/ylong_http_client/src/util/redirect.rs @@ -11,9 +11,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::error::ErrorKind; -use crate::error::HttpClientError; -use crate::util; use ylong_http::headers::Headers; use ylong_http::request::method::Method; use ylong_http::request::uri::Uri; @@ -21,6 +18,9 @@ use ylong_http::request::Request; use ylong_http::response::status::StatusCode; use ylong_http::response::Response; +use crate::error::{ErrorKind, HttpClientError}; +use crate::util; + /// Redirect strategy supports limited times of redirection and no redirect #[derive(Clone, Debug, Eq, PartialEq)] pub struct RedirectStrategy { @@ -258,14 +258,15 @@ impl Redirect { #[cfg(test)] mod ut_redirect { - use crate::redirect::Redirect; - use crate::util::config::Redirect as setting_redirect; - use crate::util::redirect::{RedirectStatus, RedirectStrategy, TriggerKind}; use ylong_http::h1::ResponseDecoder; use ylong_http::request::uri::Uri; use ylong_http::request::Request; use ylong_http::response::status::StatusCode; use ylong_http::response::Response; + + use crate::redirect::Redirect; + use crate::util::config::Redirect as setting_redirect; + use crate::util::redirect::{RedirectStatus, RedirectStrategy, TriggerKind}; /// UT test cases for `Redirect::check_redirect`. /// /// # Brief diff --git a/ylong_http_client/tests/common/async_utils.rs b/ylong_http_client/tests/common/async_utils.rs index 6381af1..dd5d704 100644 --- a/ylong_http_client/tests/common/async_utils.rs +++ b/ylong_http_client/tests/common/async_utils.rs @@ -12,6 +12,7 @@ // limitations under the License. use std::sync::Arc; + use ylong_http_client::async_impl::Client; #[macro_export] diff --git a/ylong_http_client/tests/common/mod.rs b/ylong_http_client/tests/common/mod.rs index 5c21e4a..8dd76a0 100644 --- a/ylong_http_client/tests/common/mod.rs +++ b/ylong_http_client/tests/common/mod.rs @@ -19,12 +19,9 @@ mod sync_utils; #[cfg(all(feature = "async", not(feature = "__tls")))] pub use async_utils::async_build_http_client; - #[cfg(all(feature = "async", feature = "__tls"))] pub use async_utils::async_build_https_client; - use tokio::runtime::Runtime; - #[cfg(not(feature = "__tls"))] use tokio::sync::mpsc::{Receiver, Sender}; @@ -51,10 +48,11 @@ pub struct HttpHandle { #[macro_export] macro_rules! start_http_server { ($server_fn: ident) => {{ - use hyper::service::{make_service_fn, service_fn}; - use hyper::Server; use std::convert::Infallible; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + + use hyper::service::{make_service_fn, service_fn}; + use hyper::Server; use tokio::sync::mpsc::channel; let (start_tx, start_rx) = channel::<()>(1); @@ -285,8 +283,9 @@ macro_rules! start_tls_server { let port = listener.local_addr().unwrap().port(); tokio::spawn(async move { - let mut acceptor = openssl::ssl::SslAcceptor::mozilla_intermediate(openssl::ssl::SslMethod::tls()) - .expect("SslAcceptorBuilder error"); + let mut acceptor = + openssl::ssl::SslAcceptor::mozilla_intermediate(openssl::ssl::SslMethod::tls()) + .expect("SslAcceptorBuilder error"); acceptor .set_session_id_context(b"test") .expect("Set session id error"); @@ -306,7 +305,8 @@ macro_rules! start_tls_server { let (stream, _) = listener.accept().await.expect("TCP listener accpet error"); let ssl = openssl::ssl::Ssl::new(acceptor.context()).expect("Ssl Error"); let mut stream = tokio_openssl::SslStream::new(ssl, stream).expect("SslStream Error"); - core::pin::Pin::new(&mut stream).accept().await.unwrap(); // SSL negotiation finished successfully + // SSL negotiation finished successfully + core::pin::Pin::new(&mut stream).accept().await.unwrap(); hyper::server::conn::Http::new() .http1_only(true) @@ -315,9 +315,7 @@ macro_rules! start_tls_server { .await }); - TlsHandle { - port, - } + TlsHandle { port } }}; } diff --git a/ylong_http_client/tests/sdv_async_http.rs b/ylong_http_client/tests/sdv_async_http.rs index ad7cb5c..edf98d5 100644 --- a/ylong_http_client/tests/sdv_async_http.rs +++ b/ylong_http_client/tests/sdv_async_http.rs @@ -16,11 +16,10 @@ #[macro_use] mod common; -use crate::common::async_build_http_client; -use crate::common::init_test_work_runtime; -use crate::common::HttpHandle; use ylong_http::body::async_impl::Body as AsyncBody; +use crate::common::{async_build_http_client, init_test_work_runtime, HttpHandle}; + /// SDV test cases for `async::Client`. /// /// # Brief diff --git a/ylong_http_client/tests/sdv_async_https_c_ssl.rs b/ylong_http_client/tests/sdv_async_https_c_ssl.rs index 3b12022..99033c4 100644 --- a/ylong_http_client/tests/sdv_async_https_c_ssl.rs +++ b/ylong_http_client/tests/sdv_async_https_c_ssl.rs @@ -16,12 +16,13 @@ #[macro_use] mod common; -use crate::common::async_build_https_client; -use crate::common::init_test_work_runtime; -use common::TlsHandle; use std::path::PathBuf; + +use common::TlsHandle; use ylong_http_client::Body; +use crate::common::{async_build_https_client, init_test_work_runtime}; + // TODO: Add doc for sdv tests. #[test] fn sdv_async_client_send_request() { diff --git a/ylong_http_client/tests/sdv_sync_http.rs b/ylong_http_client/tests/sdv_sync_http.rs index f5209a4..4defc6f 100644 --- a/ylong_http_client/tests/sdv_sync_http.rs +++ b/ylong_http_client/tests/sdv_sync_http.rs @@ -16,11 +16,12 @@ #[macro_use] mod common; -use crate::common::init_test_work_runtime; -use crate::common::HttpHandle; use std::sync::Arc; + use ylong_http_client::sync_impl::Body; +use crate::common::{init_test_work_runtime, HttpHandle}; + /// SDV test cases for `sync::Client`. /// /// # Brief diff --git a/ylong_http_client/tests/sdv_sync_https_c_ssl.rs b/ylong_http_client/tests/sdv_sync_https_c_ssl.rs index ad70088..2b17d9d 100644 --- a/ylong_http_client/tests/sdv_sync_https_c_ssl.rs +++ b/ylong_http_client/tests/sdv_sync_https_c_ssl.rs @@ -13,11 +13,13 @@ #![cfg(all(feature = "sync", feature = "__tls"))] -use crate::common::init_test_work_runtime; -use common::TlsHandle; use std::path::PathBuf; + +use common::TlsHandle; use ylong_http_client::sync_impl::Body; +use crate::common::init_test_work_runtime; + #[macro_use] mod common;