diff --git a/src/body.rs b/src/body.rs index 5817565c..1178e863 100644 --- a/src/body.rs +++ b/src/body.rs @@ -5,7 +5,7 @@ use std::fmt::{self, Debug}; use std::pin::Pin; use std::task::{Context, Poll}; -use crate::{mime, Mime}; +use crate::{media_type, MediaType}; use crate::{Status, StatusCode}; pin_project_lite::pin_project! { @@ -46,15 +46,15 @@ pin_project_lite::pin_project! { /// /// # Content Encoding /// - /// By default `Body` will come with a fallback Mime type that is used by `Request` and - /// `Response` if no other type has been set, and no other Mime type can be inferred. + /// By default `Body` will come with a fallback media type that is used by `Request` and + /// `Response` if no other type has been set, and no other media type can be inferred. /// - /// It's _strongly_ recommended to always set a mime type on both the `Request` and `Response`, + /// It's _strongly_ recommended to always set a media type on both the `Request` and `Response`, /// and not rely on the fallback mechanisms. However, they're still there if you need them. pub struct Body { #[pin] reader: Box, - mime: Mime, + media_type: MediaType, length: Option, bytes_read: usize } @@ -63,8 +63,8 @@ pin_project_lite::pin_project! { impl Body { /// Create a new empty `Body`. /// - /// The body will have a length of `0`, and the Mime type set to `application/octet-stream` if - /// no other mime type has been set or can be sniffed. + /// The body will have a length of `0`, and the media type set to `application/octet-stream` if + /// no other media type has been set or can be sniffed. /// /// # Examples /// @@ -77,7 +77,7 @@ impl Body { pub fn empty() -> Self { Self { reader: Box::new(io::empty()), - mime: mime::BYTE_STREAM, + media_type: media_type::BYTE_STREAM, length: Some(0), bytes_read: 0, } @@ -85,7 +85,7 @@ impl Body { /// Create a `Body` from a reader with an optional length. /// - /// The Mime type is set to `application/octet-stream` if no other mime type has been set or can + /// The media type is set to `application/octet-stream` if no other media type has been set or can /// be sniffed. If a `Body` has no length, HTTP implementations will often switch over to /// framed messages such as [Chunked /// Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding). @@ -108,7 +108,7 @@ impl Body { ) -> Self { Self { reader: Box::new(reader), - mime: mime::BYTE_STREAM, + media_type: media_type::BYTE_STREAM, length: len, bytes_read: 0, } @@ -133,7 +133,7 @@ impl Body { /// Create a `Body` from a Vec of bytes. /// - /// The Mime type is set to `application/octet-stream` if no other mime type has been set or can + /// The media type is set to `application/octet-stream` if no other media type has been set or can /// be sniffed. If a `Body` has no length, HTTP implementations will often switch over to /// framed messages such as [Chunked /// Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding). @@ -151,7 +151,7 @@ impl Body { /// ``` pub fn from_bytes(bytes: Vec) -> Self { Self { - mime: mime::BYTE_STREAM, + media_type: media_type::BYTE_STREAM, length: Some(bytes.len()), reader: Box::new(io::Cursor::new(bytes)), bytes_read: 0, @@ -183,7 +183,7 @@ impl Body { /// Create a `Body` from a String /// - /// The Mime type is set to `text/plain` if no other mime type has been set or can + /// The media type is set to `text/plain` if no other media type has been set or can /// be sniffed. If a `Body` has no length, HTTP implementations will often switch over to /// framed messages such as [Chunked /// Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding). @@ -201,7 +201,7 @@ impl Body { /// ``` pub fn from_string(s: String) -> Self { Self { - mime: mime::PLAIN, + media_type: media_type::PLAIN, length: Some(s.len()), reader: Box::new(io::Cursor::new(s.into_bytes())), bytes_read: 0, @@ -232,7 +232,7 @@ impl Body { /// Creates a `Body` from a type, serializing it as JSON. /// - /// # Mime + /// # MediaType /// /// The encoding is set to `application/json`. /// @@ -249,7 +249,7 @@ impl Body { let body = Self { length: Some(bytes.len()), reader: Box::new(io::Cursor::new(bytes)), - mime: mime::JSON, + media_type: media_type::JSON, bytes_read: 0, }; Ok(body) @@ -282,7 +282,7 @@ impl Body { /// Creates a `Body` from a type, serializing it using form encoding. /// - /// # Mime + /// # MediaType /// /// The encoding is set to `application/x-www-form-urlencoded`. /// @@ -314,7 +314,7 @@ impl Body { let body = Self { length: Some(bytes.len()), reader: Box::new(io::Cursor::new(bytes)), - mime: mime::FORM, + media_type: media_type::FORM, bytes_read: 0, }; Ok(body) @@ -351,7 +351,7 @@ impl Body { /// Create a `Body` from a file. /// - /// The Mime type set to `application/octet-stream` if no other mime type has + /// The media type set to `application/octet-stream` if no other media type has /// been set or can be sniffed. /// /// # Examples @@ -375,13 +375,13 @@ impl Body { // Look at magic bytes first, look at extension second, fall back to // octet stream. - let mime = peek_mime(&mut file) + let media_type = peek_media_type(&mut file) .await? .or_else(|| guess_ext(path)) - .unwrap_or(mime::BYTE_STREAM); + .unwrap_or(media_type::BYTE_STREAM); Ok(Self { - mime, + media_type, length: Some(len as usize), reader: Box::new(io::BufReader::new(file)), bytes_read: 0, @@ -410,14 +410,14 @@ impl Body { self.length.map(|length| length == 0) } - /// Returns the mime type of this Body. - pub fn mime(&self) -> &Mime { - &self.mime + /// Returns the media type of this Body. + pub fn media_type(&self) -> &MediaType { + &self.media_type } - /// Sets the mime type of this Body. - pub fn set_mime(&mut self, mime: impl Into) { - self.mime = mime.into(); + /// Sets the media type of this Body. + pub fn set_media_type(&mut self, media_type: impl Into) { + self.media_type = media_type.into(); } } @@ -494,26 +494,26 @@ impl AsyncBufRead for Body { } } -/// Look at first few bytes of a file to determine the mime type. +/// Look at first few bytes of a file to determine the media type. /// This is used for various binary formats such as images and videos. #[cfg(all(feature = "fs", not(target_os = "unknown")))] -async fn peek_mime(file: &mut async_std::fs::File) -> io::Result> { +async fn peek_media_type(file: &mut async_std::fs::File) -> io::Result> { // We need to read the first 300 bytes to correctly infer formats such as tar. let mut buf = [0_u8; 300]; file.read(&mut buf).await?; - let mime = Mime::sniff(&buf).ok(); + let media_type = MediaType::sniff(&buf).ok(); // Reset the file cursor back to the start. file.seek(io::SeekFrom::Start(0)).await?; - Ok(mime) + Ok(media_type) } -/// Look at the extension of a file to determine the mime type. +/// Look at the extension of a file to determine the media type. /// This is useful for plain-text formats such as HTML and CSS. #[cfg(all(feature = "fs", not(target_os = "unknown")))] -fn guess_ext(path: &std::path::Path) -> Option { +fn guess_ext(path: &std::path::Path) -> Option { let ext = path.extension().map(|p| p.to_str()).flatten(); - ext.and_then(Mime::from_extension) + ext.and_then(MediaType::from_extension) } #[cfg(test)] diff --git a/src/headers/header_value.rs b/src/headers/header_value.rs index d77cf8a0..8244e270 100644 --- a/src/headers/header_value.rs +++ b/src/headers/header_value.rs @@ -4,7 +4,7 @@ use std::str::FromStr; use crate::headers::HeaderValues; use crate::Error; -use crate::{Cookie, Mime}; +use crate::{Cookie, MediaType}; /// A header value. #[derive(Clone, Eq, PartialEq, Hash)] @@ -46,10 +46,10 @@ impl HeaderValue { } } -impl From for HeaderValue { - fn from(mime: Mime) -> Self { +impl From for HeaderValue { + fn from(media_type: MediaType) -> Self { HeaderValue { - inner: format!("{}", mime), + inner: format!("{}", media_type), } } } @@ -62,10 +62,10 @@ impl From> for HeaderValue { } } -impl From<&Mime> for HeaderValue { - fn from(mime: &Mime) -> Self { +impl From<&MediaType> for HeaderValue { + fn from(media_type: &MediaType) -> Self { HeaderValue { - inner: format!("{}", mime), + inner: format!("{}", media_type), } } } diff --git a/src/lib.rs b/src/lib.rs index c332fb54..e0625620 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -83,9 +83,9 @@ //! # The Body Type //! //! In HTTP, [`Body`](struct.Body.html) types are optional. The content of a `Body` is a stream of -//! bytes with a specific encoding; this encoding is its [`Mime` type](struct.Mime.html). The `Mime` can +//! bytes with a specific encoding; this encoding is its [`MediaType` type](struct.MediaType.html). The `MediaType` can //! be set using the [`set_content_type`](struct.Request.html#method.set_content_type) method, and -//! there are many different possible `Mime` types. +//! there are many different possible `MediaType` types. //! //! `http-types`' `Body` struct can take anything that implements //! [`AsyncBufRead`](https://docs.rs/futures/0.3.1/futures/io/trait.AsyncBufRead.html) and stream @@ -122,7 +122,7 @@ pub mod cache; pub mod conditional; pub mod content; pub mod headers; -pub mod mime; +pub mod media_type; pub mod other; pub mod proxies; pub mod server; @@ -155,7 +155,7 @@ pub use version::Version; pub use trailers::Trailers; #[doc(inline)] -pub use mime::Mime; +pub use media_type::MediaType; #[doc(inline)] pub use headers::Headers; diff --git a/src/media_type/constants.rs b/src/media_type/constants.rs new file mode 100644 index 00000000..32d6d936 --- /dev/null +++ b/src/media_type/constants.rs @@ -0,0 +1,64 @@ +use super::ParamKind; +use crate::MediaType; + +macro_rules! utf8_media_type_const { + ($name:ident, $desc:expr, $base:expr, $sub:expr) => { + media_type_const!( + with_params, + $name, + $desc, + $base, + $sub, + Some(ParamKind::Utf8), + ";charset=utf-8" + ); + }; +} +macro_rules! media_type_const { + ($name:ident, $desc:expr, $base:expr, $sub:expr) => { + media_type_const!(with_params, $name, $desc, $base, $sub, None, ""); + }; + + (with_params, $name:ident, $desc:expr, $base:expr, $sub:expr, $params:expr, $doccomment:expr) => { + media_type_const!(doc_expanded, $name, $desc, $base, $sub, $params, + concat!( + "Content-Type for ", + $desc, + ".\n\n# media type\n\n```text\n", + $base, "/", $sub, $doccomment, "\n```") + ); + }; + + (doc_expanded, $name:ident, $desc:expr, $base:expr, $sub:expr, $params:expr, $doccomment:expr) => { + #[doc = $doccomment] + pub const $name: MediaType = MediaType { + essence: String::new(), + basetype: String::new(), + subtype: String::new(), + params: $params, + static_essence: Some(concat!($base, "/", $sub)), + static_basetype: Some($base), + static_subtype: Some($sub), + }; + }; +} + +utf8_media_type_const!(JAVASCRIPT, "JavaScript", "application", "javascript"); +utf8_media_type_const!(CSS, "CSS", "text", "css"); +utf8_media_type_const!(HTML, "HTML", "text", "html"); +utf8_media_type_const!(PLAIN, "Plain text", "text", "plain"); +utf8_media_type_const!(XML, "XML", "application", "xml"); +media_type_const!(ANY, "matching anything", "*", "*"); +media_type_const!(JSON, "JSON", "application", "json"); +media_type_const!(SVG, "SVG", "image", "svg+xml"); +media_type_const!(PNG, "PNG images", "image", "png"); +media_type_const!(JPEG, "JPEG images", "image", "jpeg"); +media_type_const!(SSE, "Server Sent Events", "text", "event-stream"); +media_type_const!(BYTE_STREAM, "byte streams", "application", "octet-stream"); +media_type_const!(FORM, "forms", "application", "x-www-form-urlencoded"); +media_type_const!(MULTIPART_FORM, "multipart forms", "multipart", "form-data"); +media_type_const!(WASM, "webassembly", "application", "wasm"); +// There are multiple `.ico` media types known, but `image/x-icon` +// is what most browser use. See: +// https://en.wikipedia.org/wiki/ICO_%28file_format%29#MIME_type +media_type_const!(ICO, "ICO icons", "image", "x-icon"); diff --git a/src/mime/mod.rs b/src/media_type/mod.rs similarity index 82% rename from src/mime/mod.rs rename to src/media_type/mod.rs index ec6d9583..28012271 100644 --- a/src/mime/mod.rs +++ b/src/media_type/mod.rs @@ -16,20 +16,20 @@ use crate::headers::{HeaderValue, ToHeaderValues}; use infer::Infer; -/// An IANA media type. +/// An IANA MIME media type. /// /// ``` -/// use http_types::Mime; +/// use http_types::MediaType; /// use std::str::FromStr; /// -/// let mime = Mime::from_str("text/html;charset=utf-8").unwrap(); -/// assert_eq!(mime.essence(), "text/html"); -/// assert_eq!(mime.param("charset").unwrap(), "utf-8"); +/// let media_type = MediaType::from_str("text/html;charset=utf-8").unwrap(); +/// assert_eq!(media_type.essence(), "text/html"); +/// assert_eq!(media_type.param("charset").unwrap(), "utf-8"); /// ``` // NOTE: we cannot statically initialize Strings with values yet, so we keep dedicated static // fields for the static strings. #[derive(Clone)] -pub struct Mime { +pub struct MediaType { pub(crate) essence: String, pub(crate) basetype: String, pub(crate) subtype: String, @@ -39,18 +39,18 @@ pub struct Mime { pub(crate) params: Option, } -impl Mime { - /// Sniff the mime type from a byte slice. +impl MediaType { + /// Sniff the media type from a byte slice. pub fn sniff(bytes: &[u8]) -> crate::Result { let info = Infer::new(); - let mime = match info.get(&bytes) { + let media_type = match info.get(&bytes) { Some(info) => info.mime, - None => crate::bail!("Could not sniff the mime type"), + None => crate::bail!("Could not sniff the media type"), }; - Mime::from_str(&mime) + MediaType::from_str(&media_type) } - /// Guess the mime type from a file extension + /// Guess the media type from a file extension pub fn from_extension(extension: impl AsRef) -> Option { match extension.as_ref() { "html" => Some(HTML), @@ -63,7 +63,7 @@ impl Mime { } } - /// Access the Mime's `type` value. + /// Access the MediaType's `type` value. /// /// According to the spec this method should be named `type`, but that's a reserved keyword in /// Rust so hence prefix with `base` instead. @@ -75,7 +75,7 @@ impl Mime { } } - /// Access the Mime's `subtype` value. + /// Access the MediaType's `subtype` value. pub fn subtype(&self) -> &str { if let Some(subtype) = self.static_subtype { &subtype @@ -84,7 +84,7 @@ impl Mime { } } - /// Access the Mime's `essence` value. + /// Access the MediaType's `essence` value. pub fn essence(&self) -> &str { if let Some(essence) = self.static_essence { &essence @@ -111,8 +111,8 @@ impl Mime { } } -impl PartialEq for Mime { - fn eq(&self, other: &Mime) -> bool { +impl PartialEq for MediaType { + fn eq(&self, other: &MediaType) -> bool { let left = match self.static_essence { Some(essence) => essence, None => &self.essence, @@ -125,13 +125,13 @@ impl PartialEq for Mime { } } -impl Display for Mime { +impl Display for MediaType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { parse::format(self, f) } } -impl Debug for Mime { +impl Debug for MediaType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(essence) = self.static_essence { Debug::fmt(essence, f) @@ -141,29 +141,29 @@ impl Debug for Mime { } } -impl FromStr for Mime { +impl FromStr for MediaType { type Err = crate::Error; - /// Create a new `Mime`. + /// Create a new `MediaType`. /// - /// Follows the [WHATWG MIME parsing algorithm](https://mimesniff.spec.whatwg.org/#parsing-a-mime-type). + /// Follows the [WHATWG MIME parsing algorithm](https://media_typesniff.spec.whatwg.org/#parsing-a-media_type-type). fn from_str(s: &str) -> Result { parse::parse(s) } } -impl<'a> From<&'a str> for Mime { +impl<'a> From<&'a str> for MediaType { fn from(value: &'a str) -> Self { Self::from_str(value).unwrap() } } -impl ToHeaderValues for Mime { +impl ToHeaderValues for MediaType { type Iter = option::IntoIter; fn to_header_values(&self) -> crate::Result { - let mime = self.clone(); - let header: HeaderValue = mime.into(); + let media_type = self.clone(); + let header: HeaderValue = media_type.into(); // A HeaderValue will always convert into itself. Ok(header.to_header_values().unwrap()) diff --git a/src/mime/parse.rs b/src/media_type/parse.rs similarity index 86% rename from src/mime/parse.rs rename to src/media_type/parse.rs index a8b8c48e..20591e56 100644 --- a/src/mime/parse.rs +++ b/src/media_type/parse.rs @@ -1,10 +1,10 @@ use std::fmt; -use super::{Mime, ParamKind, ParamName, ParamValue}; +use super::{MediaType, ParamKind, ParamName, ParamValue}; -/// Parse a string into a mime type. -/// Follows the [WHATWG MIME parsing algorithm](https://mimesniff.spec.whatwg.org/#parsing-a-mime-type) -pub(crate) fn parse(input: &str) -> crate::Result { +/// Parse a string into a media type. +/// Follows the [WHATWG MIME parsing algorithm](https://media_typesniff.spec.whatwg.org/#parsing-a-media_type-type) +pub(crate) fn parse(input: &str) -> crate::Result { // 1 let input = input.trim_matches(is_http_whitespace_char); @@ -106,7 +106,7 @@ pub(crate) fn parse(input: &str) -> crate::Result { } } - Ok(Mime { + Ok(MediaType { essence: format!("{}/{}", &basetype, &subtype), basetype, subtype, @@ -117,7 +117,7 @@ pub(crate) fn parse(input: &str) -> crate::Result { }) } -/// Validates [HTTP token code points](https://mimesniff.spec.whatwg.org/#http-token-code-point) +/// Validates [HTTP token code points](https://media_typesniff.spec.whatwg.org/#http-token-code-point) fn is_http_token_code_point(c: char) -> bool { matches!(c, '!' @@ -140,7 +140,7 @@ fn is_http_token_code_point(c: char) -> bool { | '0'..='9') } -/// Validates [HTTP quoted-string token code points](https://mimesniff.spec.whatwg.org/#http-quoted-string-token-code-point) +/// Validates [HTTP quoted-string token code points](https://media_typesniff.spec.whatwg.org/#http-quoted-string-token-code-point) fn is_http_quoted_string_token_code_point(c: char) -> bool { matches!(c, '\t' | ' '..='~' | '\u{80}'..='\u{FF}') } @@ -203,14 +203,14 @@ fn collect_http_quoted_string(mut input: &str) -> (String, &str) { (value, input) } -/// Implementation of [WHATWG MIME serialization algorithm](https://mimesniff.spec.whatwg.org/#serializing-a-mime-type) -pub(crate) fn format(mime_type: &Mime, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if let Some(essence) = mime_type.static_essence { +/// Implementation of [WHATWG MIME serialization algorithm](https://media_typesniff.spec.whatwg.org/#serializing-a-media_type-type) +pub(crate) fn format(media_type_type: &MediaType, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if let Some(essence) = media_type_type.static_essence { write!(f, "{}", essence)? } else { - write!(f, "{}", &mime_type.essence)? + write!(f, "{}", &media_type_type.essence)? } - if let Some(params) = &mime_type.params { + if let Some(params) = &media_type_type.params { match params { ParamKind::Utf8 => write!(f, ";charset=utf-8")?, ParamKind::Vec(params) => { @@ -226,11 +226,11 @@ pub(crate) fn format(mime_type: &Mime, f: &mut fmt::Formatter<'_>) -> fmt::Resul .0 .chars() .flat_map(|c| match c { - '"' | '\\' => EscapeMimeValue { - state: EscapeMimeValueState::Backslash(c) + '"' | '\\' => EscapeMediaTypeValue { + state: EscapeMediaTypeValueState::Backslash(c) }, - c => EscapeMimeValue { - state: EscapeMimeValueState::Char(c) + c => EscapeMediaTypeValue { + state: EscapeMediaTypeValueState::Char(c) }, }) .collect::() @@ -243,29 +243,29 @@ pub(crate) fn format(mime_type: &Mime, f: &mut fmt::Formatter<'_>) -> fmt::Resul Ok(()) } -struct EscapeMimeValue { - state: EscapeMimeValueState, +struct EscapeMediaTypeValue { + state: EscapeMediaTypeValueState, } #[derive(Clone, Debug)] -enum EscapeMimeValueState { +enum EscapeMediaTypeValueState { Done, Char(char), Backslash(char), } -impl Iterator for EscapeMimeValue { +impl Iterator for EscapeMediaTypeValue { type Item = char; fn next(&mut self) -> Option { match self.state { - EscapeMimeValueState::Done => None, - EscapeMimeValueState::Char(c) => { - self.state = EscapeMimeValueState::Done; + EscapeMediaTypeValueState::Done => None, + EscapeMediaTypeValueState::Char(c) => { + self.state = EscapeMediaTypeValueState::Done; Some(c) } - EscapeMimeValueState::Backslash(c) => { - self.state = EscapeMimeValueState::Char(c); + EscapeMediaTypeValueState::Backslash(c) => { + self.state = EscapeMediaTypeValueState::Char(c); Some('\\') } } @@ -273,33 +273,33 @@ impl Iterator for EscapeMimeValue { fn size_hint(&self) -> (usize, Option) { match self.state { - EscapeMimeValueState::Done => (0, Some(0)), - EscapeMimeValueState::Char(_) => (1, Some(1)), - EscapeMimeValueState::Backslash(_) => (2, Some(2)), + EscapeMediaTypeValueState::Done => (0, Some(0)), + EscapeMediaTypeValueState::Char(_) => (1, Some(1)), + EscapeMediaTypeValueState::Backslash(_) => (2, Some(2)), } } } #[test] fn test() { - let mime = parse("text/html").unwrap(); - assert_eq!(mime.basetype(), "text"); - assert_eq!(mime.subtype(), "html"); + let media_type = parse("text/html").unwrap(); + assert_eq!(media_type.basetype(), "text"); + assert_eq!(media_type.subtype(), "html"); - // technically invalid mime, but allow anyway - let mime = parse("text/html;").unwrap(); - assert_eq!(mime.basetype(), "text"); - assert_eq!(mime.subtype(), "html"); + // technically invalid media_type, but allow anyway + let media_type = parse("text/html;").unwrap(); + assert_eq!(media_type.basetype(), "text"); + assert_eq!(media_type.subtype(), "html"); - let mime = parse("text/html; charset=utf-8").unwrap(); - assert_eq!(mime.basetype(), "text"); - assert_eq!(mime.subtype(), "html"); - assert_eq!(mime.param("charset").unwrap(), "utf-8"); + let media_type = parse("text/html; charset=utf-8").unwrap(); + assert_eq!(media_type.basetype(), "text"); + assert_eq!(media_type.subtype(), "html"); + assert_eq!(media_type.param("charset").unwrap(), "utf-8"); - let mime = parse("text/html; charset=utf-8;").unwrap(); - assert_eq!(mime.basetype(), "text"); - assert_eq!(mime.subtype(), "html"); - assert_eq!(mime.param("charset").unwrap(), "utf-8"); + let media_type = parse("text/html; charset=utf-8;").unwrap(); + assert_eq!(media_type.basetype(), "text"); + assert_eq!(media_type.subtype(), "html"); + assert_eq!(media_type.param("charset").unwrap(), "utf-8"); assert!(parse("text").is_err()); assert!(parse("text/").is_err()); @@ -308,7 +308,7 @@ fn test() { } /// Web Platform tests for MIME type parsing -/// From https://github.com/web-platform-tests/wpt/blob/master/mimesniff/mime-types/resources/mime-types.json +/// From https://github.com/web-platform-tests/wpt/blob/master/media_typesniff/media_type-types/resources/media_type-types.json #[test] fn whatwag_tests() { fn assert_parse(input: &str, expected: &str) { @@ -467,7 +467,7 @@ fn whatwag_tests() { assert_parse("x/x;test", "x/x"); assert_parse("x/x;test=\"\\", "x/x;test=\"\\\\\""); - // Whitespace (not handled by generated-mime-types.json or above) + // Whitespace (not handled by generated-media_type-types.json or above) assert_parse("x/x;x= ", "x/x"); assert_parse("x/x;x=\t", "x/x"); assert_parse("x/x\n\r\t ;x=x", "x/x;x=x"); diff --git a/src/mime/constants.rs b/src/mime/constants.rs deleted file mode 100644 index d9bac62e..00000000 --- a/src/mime/constants.rs +++ /dev/null @@ -1,64 +0,0 @@ -use super::ParamKind; -use crate::Mime; - -macro_rules! utf8_mime_const { - ($name:ident, $desc:expr, $base:expr, $sub:expr) => { - mime_const!( - with_params, - $name, - $desc, - $base, - $sub, - Some(ParamKind::Utf8), - ";charset=utf-8" - ); - }; -} -macro_rules! mime_const { - ($name:ident, $desc:expr, $base:expr, $sub:expr) => { - mime_const!(with_params, $name, $desc, $base, $sub, None, ""); - }; - - (with_params, $name:ident, $desc:expr, $base:expr, $sub:expr, $params:expr, $doccomment:expr) => { - mime_const!(doc_expanded, $name, $desc, $base, $sub, $params, - concat!( - "Content-Type for ", - $desc, - ".\n\n# Mime Type\n\n```text\n", - $base, "/", $sub, $doccomment, "\n```") - ); - }; - - (doc_expanded, $name:ident, $desc:expr, $base:expr, $sub:expr, $params:expr, $doccomment:expr) => { - #[doc = $doccomment] - pub const $name: Mime = Mime { - essence: String::new(), - basetype: String::new(), - subtype: String::new(), - params: $params, - static_essence: Some(concat!($base, "/", $sub)), - static_basetype: Some($base), - static_subtype: Some($sub), - }; - }; -} - -utf8_mime_const!(JAVASCRIPT, "JavaScript", "application", "javascript"); -utf8_mime_const!(CSS, "CSS", "text", "css"); -utf8_mime_const!(HTML, "HTML", "text", "html"); -utf8_mime_const!(PLAIN, "Plain text", "text", "plain"); -utf8_mime_const!(XML, "XML", "application", "xml"); -mime_const!(ANY, "matching anything", "*", "*"); -mime_const!(JSON, "JSON", "application", "json"); -mime_const!(SVG, "SVG", "image", "svg+xml"); -mime_const!(PNG, "PNG images", "image", "png"); -mime_const!(JPEG, "JPEG images", "image", "jpeg"); -mime_const!(SSE, "Server Sent Events", "text", "event-stream"); -mime_const!(BYTE_STREAM, "byte streams", "application", "octet-stream"); -mime_const!(FORM, "forms", "application", "x-www-form-urlencoded"); -mime_const!(MULTIPART_FORM, "multipart forms", "multipart", "form-data"); -mime_const!(WASM, "webassembly", "application", "wasm"); -// There are multiple `.ico` mime types known, but `image/x-icon` -// is what most browser use. See: -// https://en.wikipedia.org/wiki/ICO_%28file_format%29#MIME_type -mime_const!(ICO, "ICO icons", "image", "x-icon"); diff --git a/src/request.rs b/src/request.rs index 2296cc32..e6f66c09 100644 --- a/src/request.rs +++ b/src/request.rs @@ -11,7 +11,7 @@ use crate::headers::{ self, HeaderName, HeaderValue, HeaderValues, Headers, Names, ToHeaderValues, Values, CONTENT_TYPE, }; -use crate::mime::Mime; +use crate::media_type::MediaType; use crate::trailers::{self, Trailers}; use crate::{Body, Extensions, Method, StatusCode, Url, Version}; @@ -463,22 +463,22 @@ impl Request { /// Set the response MIME. // TODO: return a parsed MIME - pub fn set_content_type(&mut self, mime: Mime) -> Option { - let value: HeaderValue = mime.into(); + pub fn set_content_type(&mut self, media_type: MediaType) -> Option { + let value: HeaderValue = media_type.into(); - // A Mime instance is guaranteed to be valid header name. + // A MediaType instance is guaranteed to be valid header name. self.insert_header(CONTENT_TYPE, value) } /// Copy MIME data from the body. fn copy_content_type_from_body(&mut self) { if self.header(CONTENT_TYPE).is_none() { - self.set_content_type(self.body.mime().clone()); + self.set_content_type(self.body.media_type().clone()); } } /// Get the current content type - pub fn content_type(&self) -> Option { + pub fn content_type(&self) -> Option { self.header(CONTENT_TYPE)?.last().as_str().parse().ok() } diff --git a/src/response.rs b/src/response.rs index 766dacba..e72f5709 100644 --- a/src/response.rs +++ b/src/response.rs @@ -12,7 +12,7 @@ use crate::headers::{ self, HeaderName, HeaderValue, HeaderValues, Headers, Names, ToHeaderValues, Values, CONTENT_TYPE, }; -use crate::mime::Mime; +use crate::media_type::MediaType; use crate::trailers::{self, Trailers}; use crate::upgrade; use crate::{Body, Extensions, StatusCode, Version}; @@ -367,22 +367,22 @@ impl Response { } /// Set the response MIME. - pub fn set_content_type(&mut self, mime: Mime) -> Option { - let value: HeaderValue = mime.into(); + pub fn set_content_type(&mut self, media_type: MediaType) -> Option { + let value: HeaderValue = media_type.into(); - // A Mime instance is guaranteed to be valid header name. + // A MediaType instance is guaranteed to be valid header name. self.insert_header(CONTENT_TYPE, value) } /// Copy MIME data from the body. fn copy_content_type_from_body(&mut self) { if self.header(CONTENT_TYPE).is_none() { - self.set_content_type(self.body.mime().clone()); + self.set_content_type(self.body.media_type().clone()); } } /// Get the current content type - pub fn content_type(&self) -> Option { + pub fn content_type(&self) -> Option { self.header(CONTENT_TYPE)?.last().as_str().parse().ok() } diff --git a/src/security/mod.rs b/src/security/mod.rs index 257b002e..f86f1933 100644 --- a/src/security/mod.rs +++ b/src/security/mod.rs @@ -143,7 +143,7 @@ pub fn hsts(mut headers: impl AsMut) { /// Prevent browsers from trying to guess (“sniff”) the MIME type, which can have security /// implications. /// -/// [read more](https://helmetjs.github.io/docs/dont-sniff-mimetype/) +/// [read more](https://helmetjs.github.io/docs/dont-sniff-media_typetype/) /// // /// ## Examples // /// ``` diff --git a/tests/mime.rs b/tests/media_type.rs similarity index 66% rename from tests/mime.rs rename to tests/media_type.rs index a7b80328..53ccdd6f 100644 --- a/tests/mime.rs +++ b/tests/media_type.rs @@ -1,22 +1,22 @@ use async_std::fs; use async_std::io; -use http_types::{mime, Body, Response}; +use http_types::{media_type, Body, Response}; #[async_std::test] -async fn guess_plain_text_mime() -> io::Result<()> { +async fn guess_plain_text_media_type() -> io::Result<()> { let body = Body::from_file("tests/fixtures/index.html").await?; let mut res = Response::new(200); res.set_body(body); - assert_eq!(res.content_type(), Some(mime::HTML)); + assert_eq!(res.content_type(), Some(media_type::HTML)); Ok(()) } #[async_std::test] -async fn guess_binary_mime() -> http_types::Result<()> { +async fn guess_binary_media_type() -> http_types::Result<()> { let body = Body::from_file("tests/fixtures/nori.png").await?; let mut res = Response::new(200); res.set_body(body); - assert_eq!(res.content_type(), Some(mime::PNG)); + assert_eq!(res.content_type(), Some(media_type::PNG)); // Assert the file is correctly reset after we've peeked the bytes let left = fs::read("tests/fixtures/nori.png").await?; @@ -26,11 +26,11 @@ async fn guess_binary_mime() -> http_types::Result<()> { } #[async_std::test] -async fn guess_mime_fallback() -> io::Result<()> { +async fn guess_media_type_fallback() -> io::Result<()> { let body = Body::from_file("tests/fixtures/unknown.custom").await?; let mut res = Response::new(200); res.set_body(body); - assert_eq!(res.content_type(), Some(mime::BYTE_STREAM)); + assert_eq!(res.content_type(), Some(media_type::BYTE_STREAM)); Ok(()) } @@ -39,6 +39,6 @@ async fn parse_empty_files() -> http_types::Result<()> { let body = Body::from_file("tests/fixtures/empty.custom").await?; let mut res = Response::new(200); res.set_body(body); - assert_eq!(res.content_type(), Some(mime::BYTE_STREAM)); + assert_eq!(res.content_type(), Some(media_type::BYTE_STREAM)); Ok(()) }