Use data_url::Mime to parse the MIME Types

This commit follows the spectification
https://fetch.spec.whatwg.org/#concept-header-extract-mime-type
This commit is contained in:
Vincent Ricard 2020-10-29 18:03:22 +01:00
parent 15a435a7ae
commit 43b3d93aec
10 changed files with 147 additions and 60 deletions

View file

@ -10,8 +10,9 @@ use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::str::{is_token, ByteString};
use crate::dom::globalscope::GlobalScope;
use data_url::mime::Mime as DataUrlMime;
use dom_struct::dom_struct;
use http::header::{self, HeaderMap as HyperHeaders, HeaderName, HeaderValue};
use http::header::{HeaderMap as HyperHeaders, HeaderName, HeaderValue};
use net_traits::request::is_cors_safelisted_request_header;
use std::cell::Cell;
use std::str::{self, FromStr};
@ -269,10 +270,7 @@ impl Headers {
// https://fetch.spec.whatwg.org/#concept-header-extract-mime-type
pub fn extract_mime_type(&self) -> Vec<u8> {
self.header_list
.borrow()
.get(header::CONTENT_TYPE)
.map_or(vec![], |v| v.as_bytes().to_owned())
extract_mime_type(&*self.header_list.borrow()).unwrap_or(vec![])
}
pub fn sort_header_list(&self) -> Vec<(String, Vec<u8>)> {
@ -469,3 +467,72 @@ pub fn is_obs_text(x: u8) -> bool {
_ => false,
}
}
// https://fetch.spec.whatwg.org/#concept-header-extract-mime-type
// This function uses data_url::Mime to parse the MIME Type because
// mime::Mime does not provide a parser following the Fetch spec
// see https://github.com/hyperium/mime/issues/106
pub fn extract_mime_type(headers: &HyperHeaders) -> Option<Vec<u8>> {
let mut charset: Option<String> = None;
let mut essence: String = "".to_string();
let mut mime_type: Option<DataUrlMime> = None;
// Step 4
let headers_values = headers.get_all(http::header::CONTENT_TYPE).iter();
// Step 5
if headers_values.size_hint() == (0, Some(0)) {
return None;
}
// Step 6
for header_value in headers_values {
// Step 6.1
match DataUrlMime::from_str(header_value.to_str().unwrap_or("")) {
// Step 6.2
Err(_) => continue,
Ok(temp_mime) => {
let temp_essence = format!("{}/{}", temp_mime.type_, temp_mime.subtype);
// Step 6.2
if temp_essence == "*/*" {
continue;
}
let temp_charset = &temp_mime.get_parameter("charset");
// Step 6.3
mime_type = Some(DataUrlMime {
type_: temp_mime.type_.to_string(),
subtype: temp_mime.subtype.to_string(),
parameters: temp_mime.parameters.clone(),
});
// Step 6.4
if temp_essence != essence {
charset = temp_charset.map(|c| c.to_string());
essence = temp_essence.to_owned();
} else {
// Step 6.5
if temp_charset.is_none() && charset.is_some() {
let DataUrlMime {
type_: t,
subtype: st,
parameters: p,
} = mime_type.unwrap();
let mut params = p;
params.push(("charset".to_string(), charset.clone().unwrap()));
mime_type = Some(DataUrlMime {
type_: t.to_string(),
subtype: st.to_string(),
parameters: params,
})
}
}
},
}
}
// Step 7, 8
return mime_type.map(|m| format!("{}", m).into_bytes());
}