|
2 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 | 3 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ |
4 | 4 |
|
| 5 | +use data_url::mime::Mime as DataUrlMime; |
5 | 6 | use headers::HeaderMap; |
6 | 7 | use std::iter::Peekable; |
7 | | -use std::str::Chars; |
| 8 | +use std::str::{Chars, FromStr}; |
8 | 9 |
|
9 | 10 | /// <https://fetch.spec.whatwg.org/#http-tab-or-space> |
10 | 11 | const HTTP_TAB_OR_SPACE: &[char] = &['\u{0009}', '\u{0020}']; |
@@ -171,3 +172,89 @@ fn get_value_from_header_list(name: &str, headers: &HeaderMap) -> Option<String> |
171 | 172 | // Step 2 |
172 | 173 | return Some(values.collect::<Vec<&str>>().join(", ")); |
173 | 174 | } |
| 175 | + |
| 176 | +// https://fetch.spec.whatwg.org/#concept-header-extract-mime-type |
| 177 | +// This function uses data_url::Mime to parse the MIME Type because |
| 178 | +// mime::Mime does not provide a parser following the Fetch spec |
| 179 | +// see https://github.com/hyperium/mime/issues/106 |
| 180 | +fn extract_mime_type_as_dataurl_mime(headers: &HeaderMap) -> Option<DataUrlMime> { |
| 181 | + let mut charset: Option<String> = None; |
| 182 | + let mut essence: String = "".to_string(); |
| 183 | + let mut mime_type: Option<DataUrlMime> = None; |
| 184 | + |
| 185 | + // Step 4 |
| 186 | + let headers_values = get_header_value_as_list("content-type", headers); |
| 187 | + |
| 188 | + // Step 5 |
| 189 | + if headers_values.is_none() { |
| 190 | + return None; |
| 191 | + } |
| 192 | + |
| 193 | + // Step 6 |
| 194 | + for header_value in headers_values.unwrap().iter() { |
| 195 | + // Step 6.1 |
| 196 | + match DataUrlMime::from_str(header_value) { |
| 197 | + // Step 6.2 |
| 198 | + Err(_) => continue, |
| 199 | + Ok(temp_mime) => { |
| 200 | + let temp_essence = format!("{}/{}", temp_mime.type_, temp_mime.subtype); |
| 201 | + |
| 202 | + // Step 6.2 |
| 203 | + if temp_essence == "*/*" { |
| 204 | + continue; |
| 205 | + } |
| 206 | + |
| 207 | + let temp_charset = &temp_mime.get_parameter("charset"); |
| 208 | + |
| 209 | + // Step 6.3 |
| 210 | + mime_type = Some(DataUrlMime { |
| 211 | + type_: temp_mime.type_.to_string(), |
| 212 | + subtype: temp_mime.subtype.to_string(), |
| 213 | + parameters: temp_mime.parameters.clone(), |
| 214 | + }); |
| 215 | + |
| 216 | + // Step 6.4 |
| 217 | + if temp_essence != essence { |
| 218 | + charset = temp_charset.map(|c| c.to_string()); |
| 219 | + essence = temp_essence.to_owned(); |
| 220 | + } else { |
| 221 | + // Step 6.5 |
| 222 | + if temp_charset.is_none() && charset.is_some() { |
| 223 | + let DataUrlMime { |
| 224 | + type_: t, |
| 225 | + subtype: st, |
| 226 | + parameters: p, |
| 227 | + } = mime_type.unwrap(); |
| 228 | + let mut params = p; |
| 229 | + params.push(("charset".to_string(), charset.clone().unwrap())); |
| 230 | + mime_type = Some(DataUrlMime { |
| 231 | + type_: t.to_string(), |
| 232 | + subtype: st.to_string(), |
| 233 | + parameters: params, |
| 234 | + }) |
| 235 | + } |
| 236 | + } |
| 237 | + }, |
| 238 | + } |
| 239 | + } |
| 240 | + |
| 241 | + // Step 7, 8 |
| 242 | + return mime_type; |
| 243 | +} |
| 244 | + |
| 245 | +pub fn extract_mime_type(headers: &HeaderMap) -> Option<Vec<u8>> { |
| 246 | + return extract_mime_type_as_dataurl_mime(headers).map(|m| format!("{}", m).into_bytes()); |
| 247 | +} |
| 248 | + |
| 249 | +pub fn extract_mime_type_as_mime(headers: &HeaderMap) -> Option<mime::Mime> { |
| 250 | + return extract_mime_type_as_dataurl_mime(headers) |
| 251 | + .map(|m: DataUrlMime| { |
| 252 | + // Try to transform a data-url::mime::Mime into a mime::Mime |
| 253 | + let mut mime_as_str = format!("{}/{}", m.type_, m.subtype); |
| 254 | + for p in m.parameters { |
| 255 | + mime_as_str.push_str(format!("; {}={}", p.0, p.1).as_str()); |
| 256 | + } |
| 257 | + return mime_as_str.parse().ok(); |
| 258 | + }) |
| 259 | + .flatten(); |
| 260 | +} |
0 commit comments