Skip to content

Commit 32d16b8

Browse files
committed
Change Accept Mime negotiation
Previously we just checked whether one of the available mime types equaled one of the accepted mime types. This commit extends Mime with subset functionality, describing exactly a mime being accepted by an accept header.
1 parent 7d7323a commit 32d16b8

File tree

2 files changed

+41
-2
lines changed

2 files changed

+41
-2
lines changed

src/content/accept.rs

Lines changed: 2 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

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.as_str())
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)