mirror of https://github.com/fafhrd91/actix-web
impl eq for content encoding
This commit is contained in:
parent
de20d21703
commit
adf5fd82fe
|
@ -3,7 +3,9 @@
|
|||
## Unreleased - 2021-xx-xx
|
||||
### Changes
|
||||
- `HeaderMap::get_all` now returns a `std::slice::Iter`. [#2527]
|
||||
- `impl Eq` for `header::ContentEncoding`. [#2501]
|
||||
|
||||
[#2501]: https://github.com/actix/actix-web/pull/2501
|
||||
[#2527]: https://github.com/actix/actix-web/pull/2527
|
||||
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ pub struct ContentEncodingParseError;
|
|||
/// See [IANA HTTP Content Coding Registry].
|
||||
///
|
||||
/// [IANA HTTP Content Coding Registry]: https://www.iana.org/assignments/http-parameters/http-parameters.xhtml
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[non_exhaustive]
|
||||
pub enum ContentEncoding {
|
||||
/// Automatically select encoding based on encoding negotiation.
|
||||
|
|
|
@ -10,9 +10,7 @@ pub use crate::info::{ConnectionInfo, PeerAddr};
|
|||
pub use crate::rmap::ResourceMap;
|
||||
pub use crate::service::{HttpServiceFactory, ServiceRequest, ServiceResponse, WebService};
|
||||
|
||||
pub use crate::types::form::UrlEncoded;
|
||||
pub use crate::types::json::JsonBody;
|
||||
pub use crate::types::readlines::Readlines;
|
||||
pub use crate::types::{JsonBody, Readlines, UrlEncoded};
|
||||
|
||||
pub use actix_http::{Extensions, Payload, PayloadStream, RequestHead, Response, ResponseHead};
|
||||
pub use actix_router::{Path, ResourceDef, ResourcePath, Url};
|
||||
|
|
|
@ -147,6 +147,39 @@ impl Accept {
|
|||
Accept(vec![QualityItem::max(mime::TEXT_HTML)])
|
||||
}
|
||||
|
||||
// TODO: method for getting best content encoding based on q-factors, available from server side
|
||||
// and if none are acceptable return None
|
||||
|
||||
/// Extracts the most preferable mime type, accounting for [q-factor weighting].
|
||||
///
|
||||
/// If no q-factors are provided, the first mime type is chosen. Note that items without
|
||||
/// q-factors are given the maximum preference value.
|
||||
///
|
||||
/// As per the spec, will return [`mime::STAR_STAR`] (indicating no preference) if the contained
|
||||
/// list is empty.
|
||||
///
|
||||
/// [q-factor weighting]: https://datatracker.ietf.org/doc/html/rfc7231#section-5.3.2
|
||||
pub fn preference(&self) -> Mime {
|
||||
use actix_http::header::Quality;
|
||||
|
||||
let mut max_item = None;
|
||||
let mut max_pref = Quality::MIN;
|
||||
|
||||
// uses manual max lookup loop since we want the first occurrence in the case of same
|
||||
// preference but `Iterator::max_by_key` would give us the last occurrence
|
||||
|
||||
for pref in &self.0 {
|
||||
// only change if strictly greater
|
||||
// equal items, even while unsorted, still have higher preference if they appear first
|
||||
if pref.quality > max_pref {
|
||||
max_pref = pref.quality;
|
||||
max_item = Some(pref.item.clone());
|
||||
}
|
||||
}
|
||||
|
||||
max_item.unwrap_or(mime::STAR_STAR)
|
||||
}
|
||||
|
||||
/// Returns a sorted list of mime types from highest to lowest preference, accounting for
|
||||
/// [q-factor weighting] and specificity.
|
||||
///
|
||||
|
@ -196,36 +229,6 @@ impl Accept {
|
|||
|
||||
types.into_iter().map(|qitem| qitem.item).collect()
|
||||
}
|
||||
|
||||
/// Extracts the most preferable mime type, accounting for [q-factor weighting].
|
||||
///
|
||||
/// If no q-factors are provided, the first mime type is chosen. Note that items without
|
||||
/// q-factors are given the maximum preference value.
|
||||
///
|
||||
/// As per the spec, will return [`mime::STAR_STAR`] (indicating no preference) if the contained
|
||||
/// list is empty.
|
||||
///
|
||||
/// [q-factor weighting]: https://datatracker.ietf.org/doc/html/rfc7231#section-5.3.2
|
||||
pub fn preference(&self) -> Mime {
|
||||
use actix_http::header::Quality;
|
||||
|
||||
let mut max_item = None;
|
||||
let mut max_pref = Quality::MIN;
|
||||
|
||||
// uses manual max lookup loop since we want the first occurrence in the case of same
|
||||
// preference but `Iterator::max_by_key` would give us the last occurrence
|
||||
|
||||
for pref in &self.0 {
|
||||
// only change if strictly greater
|
||||
// equal items, even while unsorted, still have higher preference if they appear first
|
||||
if pref.quality > max_pref {
|
||||
max_pref = pref.quality;
|
||||
max_item = Some(pref.item.clone());
|
||||
}
|
||||
}
|
||||
|
||||
max_item.unwrap_or(mime::STAR_STAR)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -239,7 +242,7 @@ mod tests {
|
|||
assert!(test.ranked().is_empty());
|
||||
|
||||
let test = Accept(vec![QualityItem::max(mime::APPLICATION_JSON)]);
|
||||
assert_eq!(test.ranked(), vec!(mime::APPLICATION_JSON));
|
||||
assert_eq!(test.ranked(), vec![mime::APPLICATION_JSON]);
|
||||
|
||||
let test = Accept(vec
|
||||
common_header! {
|
||||
/// `Accept-Charset` header, defined in [RFC 7231 §5.3.3].
|
||||
///
|
||||
/// The `Accept-Charset` header field can be sent by a user agent to
|
||||
/// indicate what charsets are acceptable in textual response content.
|
||||
|
@ -52,10 +51,12 @@ crate::http::header::common_header! {
|
|||
/// AcceptCharset(vec![QualityItem::max(Charset::Ext("utf-8".to_owned()))])
|
||||
/// );
|
||||
/// ```
|
||||
(AcceptCharset, ACCEPT_CHARSET) => (QualityItem<Charset>)+
|
||||
///
|
||||
/// [RFC 7231 §5.3.3]: https://datatracker.ietf.org/doc/html/rfc7231#section-5.3.3
|
||||
(AcceptCharset, ACCEPT_CHARSET) => (QualityItem<Charset>)*
|
||||
|
||||
test_parse_and_format {
|
||||
// Test case from RFC
|
||||
crate::http::header::common_header_test!(test1, vec![b"iso-8859-5, unicode-1-1;q=0.8"]);
|
||||
common_header_test!(test1, vec![b"iso-8859-5, unicode-1-1;q=0.8"]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,26 +93,6 @@ common_header! {
|
|||
}
|
||||
|
||||
impl AcceptLanguage {
|
||||
/// Returns a sorted list of languages from highest to lowest precedence, accounting
|
||||
/// for [q-factor weighting].
|
||||
///
|
||||
/// [q-factor weighting]: https://datatracker.ietf.org/doc/html/rfc7231#section-5.3.2
|
||||
pub fn ranked(&self) -> Vec<Preference<LanguageTag>> {
|
||||
if self.0.is_empty() {
|
||||
return vec![];
|
||||
}
|
||||
|
||||
let mut types = self.0.clone();
|
||||
|
||||
// use stable sort so items with equal q-factor retain listed order
|
||||
types.sort_by(|a, b| {
|
||||
// sort by q-factor descending
|
||||
b.quality.cmp(&a.quality)
|
||||
});
|
||||
|
||||
types.into_iter().map(|qitem| qitem.item).collect()
|
||||
}
|
||||
|
||||
/// Extracts the most preferable language, accounting for [q-factor weighting].
|
||||
///
|
||||
/// If no q-factors are provided, the first language is chosen. Note that items without
|
||||
|
@ -139,6 +119,26 @@ impl AcceptLanguage {
|
|||
|
||||
max_item.unwrap_or(Preference::Any)
|
||||
}
|
||||
|
||||
/// Returns a sorted list of languages from highest to lowest precedence, accounting
|
||||
/// for [q-factor weighting].
|
||||
///
|
||||
/// [q-factor weighting]: https://datatracker.ietf.org/doc/html/rfc7231#section-5.3.2
|
||||
pub fn ranked(&self) -> Vec<Preference<LanguageTag>> {
|
||||
if self.0.is_empty() {
|
||||
return vec![];
|
||||
}
|
||||
|
||||
let mut types = self.0.clone();
|
||||
|
||||
// use stable sort so items with equal q-factor retain listed order
|
||||
types.sort_by(|a, b| {
|
||||
// sort by q-factor descending
|
||||
b.quality.cmp(&a.quality)
|
||||
});
|
||||
|
||||
types.into_iter().map(|qitem| qitem.item).collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -152,7 +152,7 @@ mod tests {
|
|||
assert!(test.ranked().is_empty());
|
||||
|
||||
let test = AcceptLanguage(vec![QualityItem::max("fr-CH".parse().unwrap())]);
|
||||
assert_eq!(test.ranked(), vec!("fr-CH".parse().unwrap()));
|
||||
assert_eq!(test.ranked(), vec!["fr-CH".parse().unwrap()]);
|
||||
|
||||
let test = AcceptLanguage(vec.
|
||||
// TODO: think about using private fields and smallvec
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct ContentDisposition {
|
||||
/// The disposition type
|
||||
|
|
|
@ -1,19 +1,18 @@
|
|||
//! Common extractors and responders.
|
||||
|
||||
// TODO: review visibility
|
||||
mod either;
|
||||
pub(crate) mod form;
|
||||
mod form;
|
||||
mod header;
|
||||
pub(crate) mod json;
|
||||
mod json;
|
||||
mod path;
|
||||
pub(crate) mod payload;
|
||||
mod payload;
|
||||
mod query;
|
||||
pub(crate) mod readlines;
|
||||
mod readlines;
|
||||
|
||||
pub use self::either::{Either, EitherExtractError};
|
||||
pub use self::form::{Form, FormConfig};
|
||||
pub use self::either::Either;
|
||||
pub use self::form::{Form, FormConfig, UrlEncoded};
|
||||
pub use self::header::Header;
|
||||
pub use self::json::{Json, JsonConfig};
|
||||
pub use self::json::{Json, JsonBody, JsonConfig};
|
||||
pub use self::path::{Path, PathConfig};
|
||||
pub use self::payload::{Payload, PayloadConfig};
|
||||
pub use self::query::{Query, QueryConfig};
|
||||
|
|
Loading…
Reference in New Issue