Skip to content

Commit e0ae15c

Browse files
authored
Merge pull request #389 from halvko/f-change-mime-negotiation
Change mime negotiation
2 parents 014f301 + 7524792 commit e0ae15c

File tree

2 files changed

+59
-2
lines changed

2 files changed

+59
-2
lines changed

src/content/accept.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,8 @@ impl Accept {
129129

130130
// Try and find the first encoding that matches.
131131
for accept in &self.entries {
132-
if available.contains(accept) {
133-
return Ok(accept.media_type.clone().into());
132+
if let Some(accept) = available.iter().find(|m| m.subset_eq(accept.media_type())) {
133+
return Ok(accept.clone().into());
134134
}
135135
}
136136

@@ -420,4 +420,22 @@ mod test {
420420
assert_eq!(accept.negotiate(&[mime::XML])?, mime::XML);
421421
Ok(())
422422
}
423+
424+
#[test]
425+
fn negotiate_missing_encoding() -> crate::Result<()> {
426+
let mime_html = "text/html".parse::<Mime>()?;
427+
428+
let mut browser_accept = Accept::new();
429+
browser_accept.push(MediaTypeProposal::new(mime_html, None)?);
430+
431+
let acceptable = &[mime::HTML];
432+
433+
let content_type = browser_accept.negotiate(acceptable);
434+
435+
assert!(
436+
content_type.is_ok(),
437+
"server is expected to return HTML content"
438+
);
439+
Ok(())
440+
}
423441
}

src/mime/mod.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,45 @@ impl Mime {
103103
.position(|(k, _)| k == &name)
104104
.map(|pos| self.params.remove(pos).1)
105105
}
106+
107+
/// Check if this mime is a subtype of another mime.
108+
///
109+
/// # Examples
110+
///
111+
/// ```
112+
/// // All mime types are subsets of */*
113+
/// use http_types::mime::Mime;
114+
/// use std::str::FromStr;
115+
///
116+
/// assert!(Mime::from_str("text/css").unwrap().subset_eq(&Mime::from_str("*/*").unwrap()));
117+
///
118+
/// // A mime type is subset of itself
119+
/// assert!(Mime::from_str("text/css").unwrap().subset_eq(&Mime::from_str("text/css").unwrap()));
120+
///
121+
/// // A mime type which is otherwise a subset with extra parameters is a subset of a mime type without those parameters
122+
/// assert!(Mime::from_str("text/css;encoding=utf-8").unwrap().subset_eq(&Mime::from_str("text/css").unwrap()));
123+
///
124+
/// // A mime type more general than another mime type is not a subset
125+
/// assert!(!Mime::from_str("*/css;encoding=utf-8").unwrap().subset_eq(&Mime::from_str("text/css").unwrap()));
126+
/// ```
127+
pub fn subset_eq(&self, other: &Mime) -> bool {
128+
if other.basetype() != "*" && self.basetype() != other.basetype() {
129+
return false;
130+
}
131+
if other.subtype() != "*" && self.subtype() != other.subtype() {
132+
return false;
133+
}
134+
for (name, value) in other.params.iter() {
135+
if !self
136+
.param(name.clone())
137+
.map(|v| v == value)
138+
.unwrap_or(false)
139+
{
140+
return false;
141+
}
142+
}
143+
true
144+
}
106145
}
107146

108147
impl Display for Mime {

0 commit comments

Comments
 (0)