diff --git a/ylong_http/src/h2/mod.rs b/ylong_http/src/h2/mod.rs index 9fc277461b085d64216b797116c397d95c45a486..f9c235d48e63a9c85ca58a5095ff2fdcff393017 100644 --- a/ylong_http/src/h2/mod.rs +++ b/ylong_http/src/h2/mod.rs @@ -56,8 +56,8 @@ mod error; mod frame; mod hpack; mod parts; -mod pseudo; +pub use crate::pseudo::PseudoHeaders; pub use decoder::{FrameDecoder, FrameKind, Frames, FramesIntoIter}; pub use encoder::FrameEncoder; pub use error::{ErrorCode, H2Error}; @@ -67,4 +67,3 @@ pub use frame::{ }; pub(crate) use hpack::{HpackDecoder, HpackEncoder}; pub use parts::Parts; -pub use pseudo::PseudoHeaders; diff --git a/ylong_http/src/h2/parts.rs b/ylong_http/src/h2/parts.rs index 8122ee7cc074b841647ca35819afd14f0884a448..ed77d96f011462a28e621fc17959bfe7995ae41d 100644 --- a/ylong_http/src/h2/parts.rs +++ b/ylong_http/src/h2/parts.rs @@ -12,7 +12,7 @@ // limitations under the License. use crate::h2::hpack::table::Header; -use crate::h2::pseudo::PseudoHeaders; +use crate::h2::PseudoHeaders; use crate::headers::Headers; /// HTTP2 HEADERS frame payload implementation. diff --git a/ylong_http/src/h2/pseudo.rs b/ylong_http/src/h2/pseudo.rs deleted file mode 100644 index 2a15d35e8e55746f5c8b2c5719175a66a3f85b66..0000000000000000000000000000000000000000 --- a/ylong_http/src/h2/pseudo.rs +++ /dev/null @@ -1,512 +0,0 @@ -// Copyright (c) 2023 Huawei Device Co., Ltd. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/// [Pseudo-Header fields] that may appear in http2 header fields. -/// -/// [Pseudo-Header fields]: https://httpwg.org/specs/rfc9113.html#PseudoHeaderFields -/// -/// # Note -/// The current structure is not responsible for checking every value. -// TODO: 考虑将 PseudoHeaders 拆分成 `RequestPseudo` 和 `ResponsePseudo`. -#[derive(Clone, PartialEq, Eq)] -pub struct PseudoHeaders { - authority: Option, - method: Option, - path: Option, - scheme: Option, - status: Option, -} - -// TODO: 去掉冗余的方法。 -impl PseudoHeaders { - /// Create a new `PseudoHeaders`. - pub(crate) fn new() -> Self { - Self { - authority: None, - method: None, - path: None, - scheme: None, - status: None, - } - } - - pub(crate) fn is_empty(&self) -> bool { - self.authority.is_none() - && self.method.is_none() - && self.path.is_none() - && self.scheme.is_none() - && self.status.is_none() - } - - /// Check if it contains `Authority`. - pub(crate) fn contains_authority(&self) -> bool { - self.authority.is_some() - } - - /// Get the `&str` value of `Authority`. - pub fn authority(&self) -> Option<&str> { - self.authority.as_deref() - } - - /// Set the value of `Authority`. - pub fn set_authority(&mut self, authority: Option) { - self.authority = authority; - } - - /// Take the `String` value of `Authority`. - pub(crate) fn take_authority(&mut self) -> Option { - self.authority.take() - } - - /// Check if it contains `Method`. - pub(crate) fn contains_method(&self) -> bool { - self.method.is_some() - } - - /// Get the `&str` value of `Method`. - pub fn method(&self) -> Option<&str> { - self.method.as_deref() - } - - /// Set the value of `Method`. - pub fn set_method(&mut self, method: Option) { - self.method = method; - } - - /// Take the `String` value of `Method`. - pub(crate) fn take_method(&mut self) -> Option { - self.method.take() - } - - /// Check if it contains `Path`. - pub(crate) fn contains_path(&self) -> bool { - self.path.is_some() - } - - /// Get the `&str` value of `Path`. - pub fn path(&self) -> Option<&str> { - self.path.as_deref() - } - - /// Set the value of `Path`. - pub fn set_path(&mut self, path: Option) { - self.path = path; - } - - /// Take the `String` value of `Path`. - pub(crate) fn take_path(&mut self) -> Option { - self.path.take() - } - - /// Check if it contains `Scheme`. - pub(crate) fn contains_scheme(&self) -> bool { - self.scheme.is_some() - } - - /// Get the `&str` value of `Scheme`. - pub fn scheme(&self) -> Option<&str> { - self.scheme.as_deref() - } - - /// Set the value of `Scheme`. - pub fn set_scheme(&mut self, scheme: Option) { - self.scheme = scheme; - } - - /// Take the `String` value of `Scheme`. - pub(crate) fn take_scheme(&mut self) -> Option { - self.scheme.take() - } - - /// Check if it contains `Status`. - pub(crate) fn contains_status(&self) -> bool { - self.status.is_some() - } - - /// Get the `&str` value of `Status`. - pub fn status(&self) -> Option<&str> { - self.status.as_deref() - } - - /// Set the value of `Status`. - pub fn set_status(&mut self, status: Option) { - self.status = status; - } - - /// Take the `String` value of `Status`. - pub(crate) fn take_status(&mut self) -> Option { - self.status.take() - } -} - -impl Default for PseudoHeaders { - fn default() -> Self { - PseudoHeaders::new() - } -} - -#[cfg(test)] -mod ut_pseudo_headers { - use crate::h2::pseudo::PseudoHeaders; - - /// UT test cases for `PseudoHeaders::new`. - /// - /// # Brief - /// 1. Calls `PseudoHeaders::new` to create a `PseudoHeaders`. - /// 2. Checks if the result has a default value. - #[test] - fn ut_pseudo_headers_new() { - let pseudo = PseudoHeaders::new(); - assert!(pseudo.authority.is_none()); - assert!(pseudo.method.is_none()); - assert!(pseudo.path.is_none()); - assert!(pseudo.scheme.is_none()); - assert!(pseudo.status.is_none()); - } - - /// UT test cases for `PseudoHeaders::contains_authority`. - /// - /// # Brief - /// 1. Creates a `PseudoHeaders`. - /// 2. Calls `PseudoHeaders::contains_authority` of it. - /// 3. Calls `PseudoHeaders::contains_authority` of it after its `authority` - /// is set. - /// 4. Checks the results. - #[test] - fn ut_pseudo_headers_contains_authority() { - let mut pseudo = PseudoHeaders::new(); - assert!(!pseudo.contains_authority()); - - pseudo.authority = Some(String::from("authority")); - assert!(pseudo.contains_authority()); - } - - /// UT test cases for `PseudoHeaders::authority`. - /// - /// # Brief - /// 1. Creates a `PseudoHeaders`. - /// 2. Calls `PseudoHeaders::authority` of it. - /// 3. Calls `PseudoHeaders::authority` of it after its `authority` is set. - /// 4. Checks the results. - #[test] - fn ut_pseudo_headers_authority() { - let mut pseudo = PseudoHeaders::new(); - assert!(pseudo.authority().is_none()); - - pseudo.authority = Some(String::from("authority")); - assert_eq!(pseudo.authority(), Some("authority")); - } - - /// UT test cases for `PseudoHeaders::set_authority`. - /// - /// # Brief - /// 1. Creates a `PseudoHeaders`. - /// 2. Calls `PseudoHeaders::set_authority` of it to set `authority` a - /// value. - /// 3. Checks the results. - #[test] - fn ut_pseudo_headers_set_authority() { - let mut pseudo = PseudoHeaders::new(); - assert!(pseudo.authority().is_none()); - - pseudo.set_authority(Some(String::from("authority"))); - assert_eq!(pseudo.authority(), Some("authority")); - - pseudo.set_authority(None); - assert!(pseudo.authority().is_none()); - } - - /// UT test cases for `PseudoHeaders::take_authority`. - /// - /// # Brief - /// 1. Creates a `PseudoHeaders`. - /// 2. Calls `PseudoHeaders::take_authority` of it. - /// 3. Calls `PseudoHeaders::take_authority` of it after its `authority` is - /// set. - /// 4. Checks the results. - #[test] - fn ut_pseudo_headers_take_authority() { - let mut pseudo = PseudoHeaders::new(); - assert!(pseudo.take_authority().is_none()); - - pseudo.authority = Some(String::from("authority")); - assert_eq!(pseudo.take_authority(), Some(String::from("authority"))); - } - - /// UT test cases for `PseudoHeaders::contains_method`. - /// - /// # Brief - /// 1. Creates a `PseudoHeaders`. - /// 2. Calls `PseudoHeaders::contains_method` of it. - /// 3. Calls `PseudoHeaders::contains_method` of it after its `method` is - /// set. - /// 4. Checks the results. - #[test] - fn ut_pseudo_headers_contains_method() { - let mut pseudo = PseudoHeaders::new(); - assert!(!pseudo.contains_method()); - - pseudo.method = Some(String::from("method")); - assert!(pseudo.contains_method()); - } - - /// UT test cases for `PseudoHeaders::method`. - /// - /// # Brief - /// 1. Creates a `PseudoHeaders`. - /// 2. Calls `PseudoHeaders::method` of it. - /// 3. Calls `PseudoHeaders::method` of it after its `method` is set. - /// 4. Checks the results. - #[test] - fn ut_pseudo_headers_method() { - let mut pseudo = PseudoHeaders::new(); - assert!(pseudo.method().is_none()); - - pseudo.method = Some(String::from("method")); - assert_eq!(pseudo.method(), Some("method")); - } - - /// UT test cases for `PseudoHeaders::set_method`. - /// - /// # Brief - /// 1. Creates a `PseudoHeaders`. - /// 2. Calls `PseudoHeaders::set_method` of it to set `method` a value. - /// 3. Checks the results. - #[test] - fn ut_pseudo_headers_set_method() { - let mut pseudo = PseudoHeaders::new(); - assert!(pseudo.method().is_none()); - - pseudo.set_method(Some(String::from("method"))); - assert_eq!(pseudo.method(), Some("method")); - - pseudo.set_method(None); - assert!(pseudo.method().is_none()); - } - - /// UT test cases for `PseudoHeaders::take_method`. - /// - /// # Brief - /// 1. Creates a `PseudoHeaders`. - /// 2. Calls `PseudoHeaders::take_method` of it. - /// 3. Calls `PseudoHeaders::take_method` of it after its `method` is set. - /// 4. Checks the results. - #[test] - fn ut_pseudo_headers_take_method() { - let mut pseudo = PseudoHeaders::new(); - assert!(pseudo.take_method().is_none()); - - pseudo.method = Some(String::from("method")); - assert_eq!(pseudo.take_method(), Some(String::from("method"))); - } - - /// UT test cases for `PseudoHeaders::contains_path`. - /// - /// # Brief - /// 1. Creates a `PseudoHeaders`. - /// 2. Calls `PseudoHeaders::contains_path` of it. - /// 3. Calls `PseudoHeaders::contains_path` of it after its `path` is set. - /// 4. Checks the results. - #[test] - fn ut_pseudo_headers_contains_path() { - let mut pseudo = PseudoHeaders::new(); - assert!(!pseudo.contains_path()); - - pseudo.path = Some(String::from("path")); - assert!(pseudo.contains_path()); - } - - /// UT test cases for `PseudoHeaders::path`. - /// - /// # Brief - /// 1. Creates a `PseudoHeaders`. - /// 2. Calls `PseudoHeaders::path` of it. - /// 3. Calls `PseudoHeaders::path` of it after its `path` is set. - /// 4. Checks the results. - #[test] - fn ut_pseudo_headers_path() { - let mut pseudo = PseudoHeaders::new(); - assert!(pseudo.path().is_none()); - - pseudo.path = Some(String::from("path")); - assert_eq!(pseudo.path(), Some("path")); - } - - /// UT test cases for `PseudoHeaders::set_path`. - /// - /// # Brief - /// 1. Creates a `PseudoHeaders`. - /// 2. Calls `PseudoHeaders::set_path` of it to set `path` a value. - /// 3. Checks the results. - #[test] - fn ut_pseudo_headers_set_path() { - let mut pseudo = PseudoHeaders::new(); - assert!(pseudo.path().is_none()); - - pseudo.set_path(Some(String::from("path"))); - assert_eq!(pseudo.path(), Some("path")); - - pseudo.set_path(None); - assert!(pseudo.path().is_none()); - } - - /// UT test cases for `PseudoHeaders::take_path`. - /// - /// # Brief - /// 1. Creates a `PseudoHeaders`. - /// 2. Calls `PseudoHeaders::take_path` of it. - /// 3. Calls `PseudoHeaders::take_path` of it after its `path` is set. - /// 4. Checks the results. - #[test] - fn ut_pseudo_headers_take_path() { - let mut pseudo = PseudoHeaders::new(); - assert!(pseudo.take_path().is_none()); - - pseudo.path = Some(String::from("path")); - assert_eq!(pseudo.take_path(), Some(String::from("path"))); - } - - /// UT test cases for `PseudoHeaders::contains_scheme`. - /// - /// # Brief - /// 1. Creates a `PseudoHeaders`. - /// 2. Calls `PseudoHeaders::contains_scheme` of it. - /// 3. Calls `PseudoHeaders::contains_scheme` of it after its `scheme` is - /// set. - /// 4. Checks the results. - #[test] - fn ut_pseudo_headers_contains_scheme() { - let mut pseudo = PseudoHeaders::new(); - assert!(!pseudo.contains_scheme()); - - pseudo.scheme = Some(String::from("scheme")); - assert!(pseudo.contains_scheme()); - } - - /// UT test cases for `PseudoHeaders::scheme`. - /// - /// # Brief - /// 1. Creates a `PseudoHeaders`. - /// 2. Calls `PseudoHeaders::scheme` of it. - /// 3. Calls `PseudoHeaders::scheme` of it after its `scheme` is set. - /// 4. Checks the results. - #[test] - fn ut_pseudo_headers_scheme() { - let mut pseudo = PseudoHeaders::new(); - assert!(pseudo.scheme().is_none()); - - pseudo.scheme = Some(String::from("scheme")); - assert_eq!(pseudo.scheme(), Some("scheme")); - } - - /// UT test cases for `PseudoHeaders::set_scheme`. - /// - /// # Brief - /// 1. Creates a `PseudoHeaders`. - /// 2. Calls `PseudoHeaders::set_scheme` of it to set `scheme` a value. - /// 3. Checks the results. - #[test] - fn ut_pseudo_headers_set_scheme() { - let mut pseudo = PseudoHeaders::new(); - assert!(pseudo.scheme().is_none()); - - pseudo.set_scheme(Some(String::from("scheme"))); - assert_eq!(pseudo.scheme(), Some("scheme")); - - pseudo.set_scheme(None); - assert!(pseudo.scheme().is_none()); - } - - /// UT test cases for `PseudoHeaders::take_scheme`. - /// - /// # Brief - /// 1. Creates a `PseudoHeaders`. - /// 2. Calls `PseudoHeaders::take_scheme` of it. - /// 3. Calls `PseudoHeaders::take_scheme` of it after its `scheme` is set. - /// 4. Checks the results. - #[test] - fn ut_pseudo_headers_take_scheme() { - let mut pseudo = PseudoHeaders::new(); - assert!(pseudo.take_scheme().is_none()); - - pseudo.scheme = Some(String::from("scheme")); - assert_eq!(pseudo.take_scheme(), Some(String::from("scheme"))); - } - - /// UT test cases for `PseudoHeaders::contains_status`. - /// - /// # Brief - /// 1. Creates a `PseudoHeaders`. - /// 2. Calls `PseudoHeaders::contains_status` of it. - /// 3. Calls `PseudoHeaders::contains_status` of it after its `status` is - /// set. - /// 4. Checks the results. - #[test] - fn ut_pseudo_headers_contains_status() { - let mut pseudo = PseudoHeaders::new(); - assert!(!pseudo.contains_status()); - - pseudo.status = Some(String::from("status")); - assert!(pseudo.contains_status()); - } - - /// UT test cases for `PseudoHeaders::status`. - /// - /// # Brief - /// 1. Creates a `PseudoHeaders`. - /// 2. Calls `PseudoHeaders::status` of it. - /// 3. Calls `PseudoHeaders::status` of it after its `status` is set. - /// 4. Checks the results. - #[test] - fn ut_pseudo_headers_status() { - let mut pseudo = PseudoHeaders::new(); - assert!(pseudo.status().is_none()); - - pseudo.status = Some(String::from("status")); - assert_eq!(pseudo.status(), Some("status")); - } - - /// UT test cases for `PseudoHeaders::set_status`. - /// - /// # Brief - /// 1. Creates a `PseudoHeaders`. - /// 2. Calls `PseudoHeaders::set_status` of it to set `status` a value. - /// 3. Checks the results. - #[test] - fn ut_pseudo_headers_set_status() { - let mut pseudo = PseudoHeaders::new(); - assert!(pseudo.status().is_none()); - - pseudo.set_status(Some(String::from("status"))); - assert_eq!(pseudo.status(), Some("status")); - - pseudo.set_status(None); - assert!(pseudo.status().is_none()); - } - - /// UT test cases for `PseudoHeaders::take_status`. - /// - /// # Brief - /// 1. Creates a `PseudoHeaders`. - /// 2. Calls `PseudoHeaders::take_status` of it. - /// 3. Calls `PseudoHeaders::take_status` of it after its `status` is set. - /// 4. Checks the results. - #[test] - fn ut_pseudo_headers_take_status() { - let mut pseudo = PseudoHeaders::new(); - assert!(pseudo.take_status().is_none()); - - pseudo.status = Some(String::from("status")); - assert_eq!(pseudo.take_status(), Some(String::from("status"))); - } -} diff --git a/ylong_http/src/h3/mod.rs b/ylong_http/src/h3/mod.rs index ba24510733fdcb15cf6cd4c8fde16208f3424061..d39e7b81b2574c8e444e058be3a798bc69af6d93 100644 --- a/ylong_http/src/h3/mod.rs +++ b/ylong_http/src/h3/mod.rs @@ -19,10 +19,11 @@ mod error; mod frame; mod octets; mod parts; -mod pseudo; mod qpack; // mod octets; mod stream; + +pub use crate::pseudo::PseudoHeaders; pub use decoder::FrameDecoder; pub use encoder::FrameEncoder; pub use error::{DecodeError, EncodeError, H3Error, H3ErrorCode}; @@ -31,7 +32,6 @@ pub use frame::{ SETTINGS_FRAME_TYPE, }; pub use parts::Parts; -pub use pseudo::PseudoHeaders; pub use stream::{ FrameKind, Frames, StreamMessage, CONTROL_STREAM_TYPE, QPACK_DECODER_STREAM_TYPE, QPACK_ENCODER_STREAM_TYPE, diff --git a/ylong_http/src/h3/parts.rs b/ylong_http/src/h3/parts.rs index 3f95e625dfdae5a03d5c376a8d5f7c14281650e0..6e646ac76a2c5de4d562feecdd491847b69c8e46 100644 --- a/ylong_http/src/h3/parts.rs +++ b/ylong_http/src/h3/parts.rs @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::h3::pseudo::PseudoHeaders; use crate::h3::qpack::table::NameField; +use crate::h3::PseudoHeaders; use crate::headers::Headers; /// HTTP3 HEADERS frame payload implementation. diff --git a/ylong_http/src/h3/qpack/format/encoder.rs b/ylong_http/src/h3/qpack/format/encoder.rs index 658ec38a76301bbecd58ca11b18701c4dc2e322b..0a38c9c7fa186f1366915de91422196db5981439 100644 --- a/ylong_http/src/h3/qpack/format/encoder.rs +++ b/ylong_http/src/h3/qpack/format/encoder.rs @@ -18,7 +18,6 @@ use std::sync::Arc; use std::{mem, result}; use crate::h3::parts::Parts; -use crate::h3::pseudo::PseudoHeaders; use crate::h3::qpack::encoder::{EncodeMessage, UnackFields}; use crate::h3::qpack::error::ErrorCode::DecoderStreamError; use crate::h3::qpack::error::QpackError; @@ -26,6 +25,7 @@ use crate::h3::qpack::format::decoder::{DecResult, LiteralString}; use crate::h3::qpack::integer::{Integer, IntegerDecoder, IntegerEncoder}; use crate::h3::qpack::table::{DynamicTable, NameField, SearchResult, TableIndex, TableSearcher}; use crate::h3::qpack::{DecoderInstPrefixBit, DecoderInstruction, EncoderInstruction, PrefixMask}; +use crate::h3::PseudoHeaders; use crate::headers::HeadersIntoIter; use crate::huffman::huffman_encode; diff --git a/ylong_http/src/lib.rs b/ylong_http/src/lib.rs index 6af6bfad7cadcde8168e776983f928551009ebfa..71899c8a25a4048e1cd0bef015df600022c27068 100644 --- a/ylong_http/src/lib.rs +++ b/ylong_http/src/lib.rs @@ -18,7 +18,9 @@ //! You can use these components to build a HTTP client, a HTTP server, etc. //! //! # Support HTTP Version -//! - `HTTP1.1` +//! - `HTTP/1.1` +//! - `HTTP/2` +//! - `HTTP/3` // TODO: Need doc. #[cfg(feature = "http1_1")] @@ -34,6 +36,9 @@ pub mod h3; #[cfg(feature = "huffman")] mod huffman; +#[cfg(any(feature = "http2", feature = "http3"))] +pub mod pseudo; + #[cfg(any(feature = "ylong_base", feature = "tokio_base"))] pub mod body; pub mod error; diff --git a/ylong_http/src/h3/pseudo.rs b/ylong_http/src/pseudo.rs similarity index 96% rename from ylong_http/src/h3/pseudo.rs rename to ylong_http/src/pseudo.rs index c38934f3f964b65f43316dbf72ee8b28a4371708..e8afad2c31e8bfa00c1b0e45e4fa4f083f5709e4 100644 --- a/ylong_http/src/h3/pseudo.rs +++ b/ylong_http/src/pseudo.rs @@ -11,7 +11,21 @@ // See the License for the specific language governing permissions and // limitations under the License. -/// [Pseudo-Header fields] that may appear in http2 header fields. +//! HTTP [`PseudoHeaders`], HTTP/2 uses a special pseudo-header file beginning +//! with the “:” character (ASCII 0x3a) to replace the message start line in HTTP/1.x +//! to convey the target URI, request method, and status code of the response. +//! +//! +//! # Example +//! ``` +//! use ylong_http::pseudo::PseudoHeaders; +//! let mut pseudo = PseudoHeaders::new(); +//! pseudo.set_method(Some("GET".to_string())); +//! assert_eq!(pseudo.method(), Some("GET")); +//! ``` +//! + +/// [Pseudo-Header fields] that may appear in http2 and http3 header fields. /// /// [Pseudo-Header fields]: https://httpwg.org/specs/rfc9113.html#PseudoHeaderFields /// @@ -27,6 +41,7 @@ pub struct PseudoHeaders { status: Option, } +// TODO: 去掉冗余的方法。 impl PseudoHeaders { /// Create a new `PseudoHeaders`. pub(crate) fn new() -> Self { @@ -156,7 +171,7 @@ impl Default for PseudoHeaders { #[cfg(test)] mod ut_pseudo_headers { - use crate::h3::pseudo::PseudoHeaders; + use crate::pseudo::PseudoHeaders; /// UT test cases for `PseudoHeaders::new`. ///