From ece032f0de35f9f209c6dfcc69aaa5cb57d59ddc Mon Sep 17 00:00:00 2001 From: pearzl Date: Sat, 24 Aug 2024 21:10:52 +0800 Subject: [PATCH] feat: add accept_encoding --- src/common/accept_encoding.rs | 61 +++++++++++++++++++++++++++++++++++ src/common/mod.rs | 4 +-- 2 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 src/common/accept_encoding.rs diff --git a/src/common/accept_encoding.rs b/src/common/accept_encoding.rs new file mode 100644 index 00000000..3f3dd2a4 --- /dev/null +++ b/src/common/accept_encoding.rs @@ -0,0 +1,61 @@ +use std::iter::FromIterator; + +use bytes::BytesMut; +use http::HeaderValue; + +use crate::util::FlatCsv; + +/// `Accept-Encoding` header, defined in +/// [RFC7231](https://datatracker.ietf.org/doc/html/rfc7231#section-5.3.4) +/// +/// The `Accept-Encoding` header field can be used by user agents to +/// indicate what response content-codings are +/// acceptable in the response. An `identity` token is used as a synonym +/// for "no encoding" in order to communicate when no encoding is +/// preferred. +/// +/// # ABNF +/// +/// ```text +/// Accept-Encoding = #( codings [ weight ] ) +/// codings = content-coding / "identity" / "*" +/// ``` +/// +/// # Example values +/// * `compress, gzip` +/// * `` +/// * `*` +/// * `compress;q=0.5, gzip;q=1` +/// * `gzip;q=1.0, identity; q=0.5, *;q=0` +#[derive(Clone, Debug, PartialEq)] +pub struct AcceptEncoding(FlatCsv); + +derive_header! { + AcceptEncoding(_), + name: ACCEPT_ENCODING +} + +impl AcceptEncoding { + /// Iterator the codings with weight. + pub fn iter(&self) -> impl Iterator { + self.0.iter() + } + + /// Create from a iterator of given codings with optional weigth. + pub fn from_pairs<'a>(pairs: impl Iterator)>) -> Self { + let iter = pairs.into_iter().filter_map(|(coding, q)| { + if let Some(q) = q { + let mut buf = BytesMut::new(); + buf.extend_from_slice(coding.as_bytes()); + buf.extend_from_slice(&[b';']); + buf.extend_from_slice(format!("{:.1}", q).as_bytes()); + HeaderValue::from_maybe_shared(buf.freeze()).ok() + } else { + HeaderValue::from_str(coding).ok() + } + }); + let csv: FlatCsv = FlatCsv::from_iter(iter); + + AcceptEncoding(csv) + } +} diff --git a/src/common/mod.rs b/src/common/mod.rs index be50e2e9..ef70d3e8 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -7,7 +7,7 @@ //! is used, such as `ContentType(pub Mime)`. //pub use self::accept_charset::AcceptCharset; -//pub use self::accept_encoding::AcceptEncoding; +pub use self::accept_encoding::AcceptEncoding; //pub use self::accept_language::AcceptLanguage; pub use self::accept_ranges::AcceptRanges; //pub use self::accept::Accept; @@ -128,7 +128,7 @@ macro_rules! bench_header { //mod accept; //mod accept_charset; -//mod accept_encoding; +mod accept_encoding; //mod accept_language; mod accept_ranges; mod access_control_allow_credentials;