Merge pull request #389 from halvko/f-change-mime-negotiation

Change mime negotiation
This commit is contained in:
Yosh 2021-11-29 15:16:43 +01:00 committed by GitHub
commit e0ae15c814
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 59 additions and 2 deletions

View File

@ -129,8 +129,8 @@ impl Accept {
// Try and find the first encoding that matches.
for accept in &self.entries {
if available.contains(accept) {
return Ok(accept.media_type.clone().into());
if let Some(accept) = available.iter().find(|m| m.subset_eq(accept.media_type())) {
return Ok(accept.clone().into());
}
}
@ -420,4 +420,22 @@ mod test {
assert_eq!(accept.negotiate(&[mime::XML])?, mime::XML);
Ok(())
}
#[test]
fn negotiate_missing_encoding() -> crate::Result<()> {
let mime_html = "text/html".parse::<Mime>()?;
let mut browser_accept = Accept::new();
browser_accept.push(MediaTypeProposal::new(mime_html, None)?);
let acceptable = &[mime::HTML];
let content_type = browser_accept.negotiate(acceptable);
assert!(
content_type.is_ok(),
"server is expected to return HTML content"
);
Ok(())
}
}

View File

@ -103,6 +103,45 @@ impl Mime {
.position(|(k, _)| k == &name)
.map(|pos| self.params.remove(pos).1)
}
/// Check if this mime is a subtype of another mime.
///
/// # Examples
///
/// ```
/// // All mime types are subsets of */*
/// use http_types::mime::Mime;
/// use std::str::FromStr;
///
/// assert!(Mime::from_str("text/css").unwrap().subset_eq(&Mime::from_str("*/*").unwrap()));
///
/// // A mime type is subset of itself
/// assert!(Mime::from_str("text/css").unwrap().subset_eq(&Mime::from_str("text/css").unwrap()));
///
/// // A mime type which is otherwise a subset with extra parameters is a subset of a mime type without those parameters
/// assert!(Mime::from_str("text/css;encoding=utf-8").unwrap().subset_eq(&Mime::from_str("text/css").unwrap()));
///
/// // A mime type more general than another mime type is not a subset
/// assert!(!Mime::from_str("*/css;encoding=utf-8").unwrap().subset_eq(&Mime::from_str("text/css").unwrap()));
/// ```
pub fn subset_eq(&self, other: &Mime) -> bool {
if other.basetype() != "*" && self.basetype() != other.basetype() {
return false;
}
if other.subtype() != "*" && self.subtype() != other.subtype() {
return false;
}
for (name, value) in other.params.iter() {
if !self
.param(name.clone())
.map(|v| v == value)
.unwrap_or(false)
{
return false;
}
}
true
}
}
impl Display for Mime {