hyperium / mime Goto Github PK
View Code? Open in Web Editor NEWMIMEs in Rust
Home Page: https://docs.rs/mime
License: MIT License
MIMEs in Rust
Home Page: https://docs.rs/mime
License: MIT License
Currently */*
can be parsed (per #28) and printed. This is fine, except that it means it's easy to write code that does nonsensical things like emitting Content-Type: */*
in an HTTP response.
Would it be possible to have two types, one that covers just RFC2045/RFC6838 media types, and a separate one that covers all RFC7231 media-range
s? Then we could define struct ContentType( t: MediaType )
and struct Accept( t: vec![(MediaRange,f32)])
, making it clear what is allowed where.
Maybe for back-compatibility Mime
could be aliased to MediaRange
.
Generated by Firefox headers
Host: example.dev
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:53.0) Gecko/20100101 Firefox/53.0
Accept: application/json
Accept-Language: uk,ru;q=0.8,ru-RU;q=0.6,en-US;q=0.4,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://example.dev/blog/3
Content-Length: 664
Content-Type: multipart/form-data; boundary=---------------------------533179479757881361497406803
Cookie: SID=a9201fa6-35f6-4d87-a6b6-89c74d48d0d3
DNT: 1
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Form data:
-----------------------------533179479757881361497406803
Content-Disposition: form-data; name="_wid"
f04f9a42-5afa-4cb6-a71c-de697c3db4e3
-----------------------------533179479757881361497406803
Content-Disposition: form-data; name="doc"
[skipped]
-----------------------------533179479757881361497406803--
Trace
:: parse Content-Type Raw([b"multipart/form-data;\x20boundary=---------------------------533179479757881361497406803"])
:: parse_header 3 Content-Type Raw([b"multipart/form-data;\x20boundary=---------------------------533179479757881361497406803"])
:: from_raw_str s "multipart/form-data; boundary=---------------------------533179479757881361497406803"
:: mime::Mime::from_str s "multipart/form-data; boundary=---------------------------533179479757881361497406803"
:: mime::parse s "multipart/form-data; boundary=---------------------------533179479757881361497406803"
:: mime::parse type loop next Some((0, 109)) 'm'
:: mime::parse type loop next Some((1, 117)) 'u'
:: mime::parse type loop next Some((2, 108)) 'l'
:: mime::parse type loop next Some((3, 116)) 't'
:: mime::parse type loop next Some((4, 105)) 'i'
:: mime::parse type loop next Some((5, 112)) 'p'
:: mime::parse type loop next Some((6, 97)) 'a'
:: mime::parse type loop next Some((7, 114)) 'r'
:: mime::parse type loop next Some((8, 116)) 't'
:: mime::parse type loop next Some((9, 47)) '/'
:: mime::parse sublevel loop next Some((10, 102)) 'f'
:: mime::parse sublevel loop next Some((11, 111)) 'o'
:: mime::parse sublevel loop next Some((12, 114)) 'r'
:: mime::parse sublevel loop next Some((13, 109)) 'm'
:: mime::parse sublevel loop next Some((14, 45)) '-'
:: mime::parse sublevel loop next Some((15, 100)) 'd'
:: mime::parse sublevel loop next Some((16, 97)) 'a'
:: mime::parse sublevel loop next Some((17, 116)) 't'
:: mime::parse sublevel loop next Some((18, 97)) 'a'
:: mime::parse sublevel loop next Some((19, 59)) ';'
:: mime::params_from_str s "; boundary=---------------------------533179479757881361497406803"
:: mime::params_from_str name loop next Some((20, 32)) ' '
:: mime::params_from_str name loop next Some((21, 98)) 'b'
:: mime::params_from_str name loop next Some((22, 111)) 'o'
:: mime::params_from_str name loop next Some((23, 117)) 'u'
:: mime::params_from_str name loop next Some((24, 110)) 'n'
:: mime::params_from_str name loop next Some((25, 100)) 'd'
:: mime::params_from_str name loop next Some((26, 97)) 'a'
:: mime::params_from_str name loop next Some((27, 114)) 'r'
:: mime::params_from_str name loop next Some((28, 121)) 'y'
:: mime::params_from_str name loop next Some((29, 61)) '='
:: mime::params_from_str value !is_quoted loop next Some((30, 45)) '-'
:: mime::Mime::from_str parse Err(InvalidToken)
Lines 131 to 132 in fda8cf1
If I have a string with mime type, I can have it parsed using the FromStr
trait. But that one takes a &str
and allocates a new copy of the string.
Would it be possible to add an allocation-less consuming constructor that would just use the passed String
?
This works in 6fd92cd, but not in 0451bea from #21:
#[macro_use]
extern crate mime;
use mime::*;
pub fn returns_mime() -> Mime {
mime!(Text/Html;Charset=Utf8)
}
In 0451bea you have to write
pub fn returns_mime() -> Mime<[(mime::Attr, mime::Value); 1]>
which is way too verbose.
This also means you can't build current hyper master with current mime.rs master.
Can I get a release w/ the serde
support for my downstream crate formdata
?
Parameter values can be quoted strings which:
\"
) (currently rejected)At last fixing the later one can cause a problem with Name::is_str(&self) -> str
,
which is not returning the underlying string representation (it strips the quotes).
But neither is it returning the content as a string as it can not unescape the
escape sequences. You still can treat it as always returning the inner part
of the value as quoted string, which would be correct, but I fear people won't do that.
For the next braking release I would have following idea:
Name::is_str
(or better have Name
for names and Value
for values and do not have is_str
on Value
)str_repr(&self) -> &str
returning the underlying str representation including quotes if there had been any, this is nice if you e.g. can only allow ascii values as you now do not need to recheck them if they are not quotedto_content_str(&self) -> Cow<'a, str>
which:
Borrowed(self.str_repr())
if it's not quotedBorrowed(&self.str_repr()[1..self.str_repr().len()-1])
(+- optimiz) for quoted value not containing escape sequencesOwned(unquoteself.str_repr()))
which returns the string represented by the quoted-string by undoing any quoting escapes etc.With Hyper on its way to 1.0, perhaps it's time to start discussing where this crate is at in relation to its own eventual 1.0 release, as well as create a place to document potential blockers for said release. That said, I haven't looked too closely at this crate lately so I don't know what any potential blockers might be.
Thoughts, @seanmonstar?
add the mime type application/wasm
as defined by the w3c spec at https://webassembly.github.io/spec/web-api/index.html#compile-a-potential-webassembly-response.
It would be great to add these MIME types/subtypes, so that applications like lettre_email can build MIME messages to send encrypted/signed email.
The serde bump is a breaking change and wasn't released on crates.io.
This is what the constant looks like on the module doc page:
That /
is actually in italic, it's just very hard to notice. This happens because the */*
string is interpreted as markdown when used as a doc comment (relevant part of the source). An easy solution would be to wrap the constant value in an inline code tag (#[doc = concat!('`', $src, '`')]
), but to preserve the formatting and just fix STAR_STAR
, the $src
would need to be escaped somehow.
Right now, in order to do 2018-style macro use, you need to do
use mime::{__mime__ident_or_ext, mime};
as opposed to just use mime::mime;
. https://rust-lang-https://rust-lang-nursery.github.io/edition-guide/rust-2018/macros/macro-changes.html#more-details has a guide on supporting this
Parsing text/event-stream;
gives a Mime
value whose subtype is event-stream;
, that seems wrong to me.
According to RFC 2046, the value of the boundary parameter is case sensitive. to_ascii_lowercase()
of the whole raw value is inappropriate.
content-type: multipart/form-data; boundary=ABCdefg
The target domain of the mime
crate is webdev. Instead of following the original RFCs (as is done now), perhaps it's best to just use the sniffing algorithm that is now used by web browsers.
mime 0.3.10 was published < an hour ago (https://crates.io/crates/mime), and has merged 62c82fd which was not backwards compatible.
This seems to have been noted (62c82fd#diff-80398c5faae3c069e4e6aa2ed11b28c0R12) but the publish appears to have happened anyway.
This is causing builds of reqwest to fail - namely https://github.com/seanmonstar/reqwest/blob/v0.9.2/src/response.rs#L211-L218 with the following:
Compiling mime v0.3.10
...
Compiling reqwest v0.9.2
error[E0599]: no method named `as_str` found for type `mime::Value<'_>` in the current scope
--> /opt/rust/registry/src/github.com-1ecc6299db9ec823/reqwest-0.9.2/src/response.rs:216:44
|
216 | .map(|charset| charset.as_str())
| ^^^^^^
error: aborting due to previous error
I cloned the repo for the master branch and the compile returns an error as follows:
error: failed to parse manifest at `/home/data/gbonnema/projects/rust/mime/Cargo.toml`
Caused by:
feature `rename-dependency` is required
this Cargo does not support nightly features, but if you
switch to nightly channel you can add
`cargo-features = ["rename-dependency"]` to enable this feature
I added the line cargo-features, but nothing changed. I fear, if I switch to nightly channel, this will affect other projects as well.
Is it possible to not have the rename-dependency
? What else can I do to correct the situation?
I am pretty new to both Rust and Mime and I hope you can help me with a small programming issue I have. I am changing an older project to work with 0.3 in stead of 0.2.6, but my understanding of what it is trying to do and how to change is lacking. Could you help me?
This is the code I want to alter:
135 // Construct a multipart body
136 let mut multipart = Multipart::new();
- let content_type = mime::Mime(
- mime::TopLevel::Application,
- mime::SubLevel::OctetStream,
- vec![],
- );
137 let content_type = mime::APPLICATION_OCTET_STREAM;
138 multipart.add_stream(
139 UPM_UPLOAD_FIELD_NAME,
140 Cursor::new(database_bytes),
141 Some(database_name),
142 Some(content_type),
143 );
144 let mut multipart_prepared = match multipart.prepare() {
145 Ok(p) => p,
146 Err(_) => return Err(UpmError::Sync(String::from("Cannot prepare file upload"))),
147 };
148 let mut multipart_buffer: Vec<u8> = vec![];
149 multipart_prepared.read_to_end(&mut multipart_buffer)?;
150
151 // Send request
152 let mut response = self.client
153 .post(&url)
154 .basic_auth(self.http_username.clone(), Some(self.http_password.clone()))
155 .header("ContentType", mime::Mime(
156 mime::TopLevel::Multipart,
157 mime::SubLevel::FormData,
158 vec![
159 (
160 mime::Attr::Ext(String::from(BOUNDARY_ATTRIBUTE)),
161 mime::Value::Ext(
162 String::from(multipart_prepared.boundary()),
163 )
164 ),
165 ],
166 ))
167 .body(multipart_buffer)
168 .send()?;
As you can see, line 137 is a replacement, which I could do, because of en ampty vector. However, I am at a loss how to replace the lines 155 - 166.
I tried to figure out how the mime::Mime( ... ) function works, but I couldn't find it (a newbie problem I am afraid).
Could you point me in the right direction?
Kind regards, Guus Bonnema.
https://github.com/web-platform-tests/wpt/blob/master/fetch/api/basic/scheme-data.any.js expects to see specifically uppercase US-ASCII. This may be counterintuitive given RFC 7231! Even though charset names are case-insensitive within the context of http algorithms, it seems that the web platform tests expect their string case to be preserved when a specification (RFC 2397 here) has set a specific case.
https://github.com/servo/servo is currently using this Mime class and is trying to pass WPT tests.
Any chance to get the serde
feature updated for serde 0.9?
mime/mime-parse/src/rfc7231.rs
Line 400 in 2e0268e
let mime = parse("text/plain; charset=\"utf-8\"").unwrap();
Parsing quoted parameters directly contradicts with RFC 2045:
Note that the value of a quoted string parameter does not include the
quotes. That is, the quotation marks in a quoted-string are not a
part of the value of the parameter, but are merely used to delimit
that parameter value. In addition, comments are allowed in
accordance with RFC 822 rules for structured header fields. Thus the
following two forms
Content-type: text/plain; charset=us-ascii (Plain text)
Content-type: text/plain; charset="us-ascii"
are completely equivalent.
Am I reading it incorrectly?
I need to be able to enumerate all parameters when picking a response type given an Accept
header.
Compiling mime v0.0.1 (https://github.com/seanmonstar/mime.rs#d9a80eea)
\.cargo\git\checkouts\mime.rs-bb2736419bbdb48d\master\src\lib.rs:28:5: 28:28 error: unresolved import `std::ascii::StrAsciiExt`. There is no `StrAsciiExt` in `std::ascii`
\.cargo\git\checkouts\mime.rs-bb2736419bbdb48d\master\src\lib.rs:28 use std::ascii::StrAsciiExt;
error: aborting due to previous error
Could not compile `mime`.
Compiling mime v0.0.8
<log macros>:4:8: 4:21 error: mismatched types:
expected `usize`,
found `u32`
(expected usize,
found u32) [E0308]
<log macros>:4 line : line ! ( ) , file : file ! ( ) , module_path : module_path ! ( ) , }
^~~~~~~~~~~~~
<log macros>:4:8: 4:21 error: mismatched types:
expected `usize`,
found `u32`
(expected usize,
found u32) [E0308]
<log macros>:4 line : line ! ( ) , file : file ! ( ) , module_path : module_path ! ( ) , }
^~~~~~~~~~~~~
<log macros>:4:8: 4:21 error: mismatched types:
expected `usize`,
found `u32`
(expected usize,
found u32) [E0308]
<log macros>:4 line : line ! ( ) , file : file ! ( ) , module_path : module_path ! ( ) , }
^~~~~~~~~~~~~
<log macros>:4:8: 4:21 error: mismatched types:
expected `usize`,
found `u32`
(expected usize,
found u32) [E0308]
<log macros>:4 line : line ! ( ) , file : file ! ( ) , module_path : module_path ! ( ) , }
^~~~~~~~~~~~~
<log macros>:4:8: 4:21 error: mismatched types:
expected `usize`,
found `u32`
(expected usize,
found u32) [E0308]
<log macros>:4 line : line ! ( ) , file : file ! ( ) , module_path : module_path ! ( ) , }
^~~~~~~~~~~~~
<log macros>:4:8: 4:21 error: mismatched types:
expected `usize`,
found `u32`
(expected usize,
found u32) [E0308]
<log macros>:4 line : line ! ( ) , file : file ! ( ) , module_path : module_path ! ( ) , }
^~~~~~~~~~~~~
<log macros>:4:8: 4:21 error: mismatched types:
expected `usize`,
found `u32`
(expected usize,
found u32) [E0308]
<log macros>:4 line : line ! ( ) , file : file ! ( ) , module_path : module_path ! ( ) , }
^~~~~~~~~~~~~
<log macros>:4:8: 4:21 error: mismatched types:
expected `usize`,
found `u32`
(expected usize,
found u32) [E0308]
<log macros>:4 line : line ! ( ) , file : file ! ( ) , module_path : module_path ! ( ) , }
^~~~~~~~~~~~~
<log macros>:4:8: 4:21 error: mismatched types:
expected `usize`,
found `u32`
(expected usize,
found u32) [E0308]
<log macros>:4 line : line ! ( ) , file : file ! ( ) , module_path : module_path ! ( ) , }
^~~~~~~~~~~~~
<log macros>:4:8: 4:21 error: mismatched types:
expected `usize`,
found `u32`
(expected usize,
found u32) [E0308]
<log macros>:4 line : line ! ( ) , file : file ! ( ) , module_path : module_path ! ( ) , }
^~~~~~~~~~~~~
<log macros>:4:8: 4:21 error: mismatched types:
expected `usize`,
found `u32`
(expected usize,
found u32) [E0308]
<log macros>:4 line : line ! ( ) , file : file ! ( ) , module_path : module_path ! ( ) , }
^~~~~~~~~~~~~
<log macros>:4:8: 4:21 error: mismatched types:
expected `usize`,
found `u32`
(expected usize,
found u32) [E0308]
<log macros>:4 line : line ! ( ) , file : file ! ( ) , module_path : module_path ! ( ) , }
^~~~~~~~~~~~~
<log macros>:4:8: 4:21 error: mismatched types:
expected `usize`,
found `u32`
(expected usize,
found u32) [E0308]
<log macros>:4 line : line ! ( ) , file : file ! ( ) , module_path : module_path ! ( ) , }
^~~~~~~~~~~~~
error: aborting due to 13 previous errors
Build failed, waiting for other jobs to finish...
Could not compile `mime`.
The following panics:
let s = "video/mp4; codecs=\"a,b\"; width=1024; Height=768; FrameRate=60; BITRATE=100000";
let m = Mime::from_str(s).unwrap();
with:
thread 'main' panicked at 'called Result::unwrap()
on an Err
value: FromStrError { inner: InvalidToken { pos: 23, byte: 59 } }', /checkout/src/libcore/result.rs:906:4
I'm guessing this is because that mime string has more than one ';' character in it.
YouTube uses MIME types in this format.
http://seanmonstar.github.io/mime.rs
A rename from mime.rs to mime-rs might help?
Hi,
would it be appropriate to make the Mime
type Deserialize
and Serialize
(possibly behind a feature gate)?
I would like to use that in one of my projects and implementing it myself seems to be possible, but if others could use that it would be better to do it here in this crate, I suppose?
The commit bbc9f80 broke the build on Rust 1.15:
$ rustup run 1.15.0 cargo build
Compiling mime v0.2.5 (file:///mnt/data/Projects/mime.rs)
error[E0001]: unreachable pattern
--> src/lib.rs:165:21
|
165 | _ => false
| ^ this is an unreachable pattern
...
294 | enoom! {
| _- starting here...
295 | | pub enum Value;
296 | | Ext;
297 | | Utf8, "utf-8";
298 | | }
| |_- ...ending here: in this macro invocation
error: aborting due to previous error
error: Could not compile `mime`.
To learn more, run the command again with --verbose.
Is that acceptable? If yes, could you state the minimal supported Rust version in the README and add 1.15 as a target to Travis?
I'm getting following error today from cargo test. My project does not use mime directly, but some crates I used might have. Any clues?
Compiling mime_guess v2.0.0
Compiling mime v0.3.13
error[E0658]: renaming imports with _
is unstable (see issue #48216)
--> /usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/mime_guess-2.0.0/build.rs:120:9
|
120 | use std::fmt::Write as _;
| ^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try rustc --explain E0658
.
error: Could not compile mime_guess
.
warning: build failed, waiting for other jobs to finish...
error: build failed
Note: it was ok when for mime_guess v2.0.0-alpha.6.
error: to use a constant of type `hyper::<unnamed>::Mime` in a pattern, `hyper::<unnamed>::Mime` must be annotated with `#[derive(PartialEq, Eq)]`
--> src/lib.rs:560:33
|
560 | TEXT_HTML => ".html",
| ^^^^^^^^^
(I'm not sure whether I can make time soon for a small PR.)
Because of #[derive(Show)]
on Mime
, and usage of value.fmt(...)
in ContentType
header formatter code (in @hyperium/hyper), I get invalid content type header like Content-Type: Mime(Application, WwwFormUrlEncoded, [])
, which leads to malfunction in client-server communications.
I guess this is not in the standard, though I'd like to define own mime types, would you add such a feature?
+ /usr/bin/cargo test --release -j6 --no-fail-fast
Fresh version_check v0.1.3
Fresh unicase v2.1.0
Compiling mime v0.3.7 (file:///builddir/build/BUILD/mime-0.3.7)
Running `/usr/bin/rustc --crate-name mime src/lib.rs --emit=dep-info,link -C opt-level=3 --test -C metadata=983a2fdb57c25688 -C extra-filename=-983a2fdb57c25688 --out-dir /builddir/build/BUILD/mime-0.3.7/target/release/deps -L dependency=/builddir/build/BUILD/mime-0.3.7/target/release/deps --extern unicase=/builddir/build/BUILD/mime-0.3.7/target/release/deps/libunicase-c368d6b2dc8b5ecf.rlib -Copt-level=3 -Cdebuginfo=2 -Clink-arg=-Wl,-z,relro,-z,now`
error: unused return value of `std::iter::Iterator::collect` which must be used
--> src/lib.rs:618:13
|
618 | / [
619 | | $(
620 | | mime_constant_test! {
621 | | $id, $($piece),*
... |
625 | | assert_eq!(pos + 1, atom as usize, "atom {} in position {}", atom, pos + 1);
626 | | }).collect::<Vec<()>>();
| |____________________________________^
...
694 | / mimes! {
695 | | STAR_STAR, "*/*", 1;
696 | |
697 | | TEXT_STAR, "text/*", 4;
... |
724 | | MULTIPART_FORM_DATA, "multipart/form-data", 9;
725 | | }
| |_- in this macro invocation
|
note: lint level defined here
--> src/lib.rs:27:9
|
27 | #![deny(warnings)]
| ^^^^^^^^
= note: #[deny(unused_must_use)] implied by #[deny(warnings)]
= note: if you really need to exhaust the iterator, consider `.for_each(drop)` instead
error: aborting due to previous error
error: Could not compile `mime`.
This is due to added #[must_use]
to .collect()
.
Hi I am implementing a PR on servo and I am using mime to sned conten-type to xhr.send and apparently Mime.to_string()
is returning i.e. text/html; charset=utf8
and mozilla's WebIDL expect it to be text/html;charset=UTF-8
.
Could/should that be changed? If yes, let me know that I send a PR.
When implementing the fetch spec for servo, I came across MIME types such as image/svg+xml
and application/xhtml+xml
. Currently mime.rs
does not contain any sublevel types that match these extended MIME types, and simply using, as in the two example, Sublevel::Xml
, to represent them is not ideal, since these could be in a vector of MIME types in the header that may contain a TopLevel
that matches and an actual SubLevel
of Xml
.
It looks like that there is no way to construct a custom Name
value without going through Mime::from_str
. It is only possible to use predefined ones, like mime::TEXT
or mime::HTML
. This is quite inconvenient if there is a need to work with type_()
and subtype()
methods. For example, I would like to check whether the given Mime
s subtype is xhtml
(as in application/xhtml+xml
) in a generic match context, like this:
let XHTML = ???; // "xhtml"
match mime.subtype() {
mime::HTML => "html",
XHTML => "xhtml",
mime::JPEG => "jpg",
mime::PNG => "png",
mime::GIF => "gif",
_ => "unknown"
}
but there is simply no way to do it.
IMO, ideally there should be a way to define const
values of Name
and Mime
types, precisely for use cases like this. At the moment, the constants provided by the library feel "blessed" somehow, compared to custom values which users of the library would potentially like to create.
I tried to add
IMAGE_SVG, "image/svg+xml", 5, Some(9);
But I get syntax errors. How should I pass the plus option parameter? Am I doing something wrong?
tl;dr: We should provide a trait that, when implemented, provides a method or a static informing the trait implementor's MIME type.
some discussion: HTTP would be pretty limited if it could only meaningfully communicate HTML documents. Beyond just making it possible for browsers to understand multimedia, MIMEs potentially allow all types of transfers to happen in HTTP.
Ideally, this would mean that machines could easily speak to other machines on the web, by allowing them to specify what languages they can use (through Accept/Content-Type headers, for example). That only works, obviously, if they agree on the MIMEs, which is the rationale for having IANA keep track of them.
Obviously, that is not sufficient for the diversity of application protocols. The convention to deal with this was to prefix x- to unofficial MIME types, such as application/x-mycustomformat. That convention was recommended, but has since been deprecated. Basically, it's counterproductive to the goal of machines speaking to each other, and it pollutes the name space. The new recommendation is to choose a sensible name, assuming it will become a standard or commonly used (because that happens).
AFAIK, as it is, whenever you want to pass or accept some content through HTTP in Rust in your preferred framework, you probably have to set the headers manually if it's not a trivial format (text/html); or, at least, you have to inform the MIME. That is, if you remembered you should pass meaningful format information in the headers.
We do fantastic with serialization already. All it takes is a #[derive(Serialize, Deserialize)]
on your struct, and you can pass or accept it through HTTP, for example. But you'd have to remember you need to inform the MIME of this serialized data and manually set the relevant header(s). You also have to guess the MIME if it's not a standard format.
Even if not too much of a bother, this is problematic, because it likely won't be the same guess another Rust programmer will make on some other application, fragmenting the web and the ecosystem.
The way we do better is by correctly delegating the responsibilities. HTTP frameworks handle setting the headers, and the MIME is informed by a trait implementation on the struct you are trying to pass. That is where mime could come in: providing this trait for other libraries.
Or it doesn't make any sense?
It is used by almost all websites on the internet.
Here is my test case.
I constructed the mime-types from content-type http headers I found.
https://play.rust-lang.org/?gist=240a00d7a9e8b949868a9c269cbeca2d&version=stable
Depending on where the Media Type is used it can have different grammar.
The main difference is between Media Types wrt. HTTP and Media Types wrt. MIME,
for the later on there are also additional aspects, like if it does appear in an internationalized
mail.
So we need at last a way to parametrize the parser, maybe more.
HTTP uses linear whitespaces which are either ' '
or '\t'
but MIME use FWS which can contain soft line breaks ("\r\n "
and "\r\n\t"
)
"token" in HTTP Media Types can not contain {
, }
but "token" in MIME Media Types can,
tokens registered with IANA a further constraint (rfc6838)
For HTTP this can be ignored but MIME defines type/subtype to either be iana-token
, ietf-token
or x-token
. Both iana-token
and ietf-token
are tokens registered with IANA and therefore are restricted by rfc6838. Also the restrictions in rfc6838 do also apply to parameter for registered Media Types, which also means they do not apply if either type or subtype are x-tokens
additionally rfc6532 introduces internationalized mails and extends quoted-string
to be able to contain all non-us-ascii-UTF-8 character, which HTTP does not allow (excluding obsolete syntax for now) but only in internationalized mails
then there is rfc2231 which allows the encoding of parameter of Media Types in MIME (not HTTP) based on any registered charset. And adds support for specifying the language which is meant to be usefull for screen readers and allows spliting parameters into multiple parts to compline with Mail line length limits.
[EDIT] in MIME Content-Type headers Media-Types can contain comments which the parser should skip over, for HTTP/1.1 this is malformed
And that is if we ignore the obsolete syntax if we include it then
DEL
/0x7f
, except '\t'
, '\n'
, '\r'
through they could already be contained before, that doesn't change)I was browsing the git repo to find the current crate from crate.io (0.3.13) and ..... I couldn't find it! Weird because it is the version from crate.io. Now I am new to rust, so I may be missing something, but should that version be somewhere in the master branch of git?
Using tig I found immediately after 0.3.6 a commit saying "prevent publishing master as 0.3.x" and no "0.3.13" thereafter. This all while `crate search mime" gets mime version="0.3.13".
When you have time, could you enlighten me how this works?
EDIT : using gitg I saw that 0.3.13 is in a non-master branch, a specific 0.3.x branch.
What is the reasoning behind this? Why isn't 4.0-alpha in a separate branch instead? I just want to understand. If you don't like the query, just close it, no offense taken.
The following strings fail to parse as valid MIMES:
application/dash+xml; codecs=vorbis,vp8
application/dash+xml; codecs=vorbis,vp8.0
application/dash+xml; codecs=xyz,vorbis
application/dash+xml; codecs=vorbis,xyz
application/dash+xml; codecs=xyz,vp8.0
application/dash+xml; codecs=vp8.0,xyz
video/ogg; codecs=vorbis,theora
video/ogg; codecs=xyz,vorbis
video/ogg; codecs=vorbis,xyz
audio/wave; codecs=xyz,1
audio/wave; codecs=1,xyz
video/webm; codecs=xyz,vorbis
video/webm; codecs=vorbis,xyz
audio/wave; codecs=""
It seems that multiple values not enclosed by quotes fail to parse. Strings with multiple values enclosed in quotes seem to work, such as "video/ogg; codecs="vorbis, theora"".
The last one in that list looks like a different problem, maybe empty values being rejected?
I extracted these strings from Firefox's media playback "canplaytype" unit tests, they're representative of the types of strings you find on the wider Internet.
Below is my full test, with all Firefox's media playback "canplaytype" tests' MIME types strings, it prints the failed cases. I'd expect these to parse successfully, though some of the values are silly.
extern crate mime;
use mime::Mime;
use std::str::FromStr;
fn main() {
let test_cases = [
"application/dash+xml",
"application/dash+xml; codecs=vorbis",
"application/dash+xml; codecs=vorbis",
"application/dash+xml; codecs=vorbis,vp8",
"application/dash+xml; codecs=vorbis,vp8.0",
"application/dash+xml; codecs=\"vorbis,vp8\"",
"application/dash+xml; codecs=\"vorbis,vp8.0\"",
"application/dash+xml; codecs=\"vp8, vorbis\"",
"application/dash+xml; codecs=\"vp8.0, vorbis\"",
"application/dash+xml; codecs=vp8",
"application/dash+xml; codecs=vp8.0",
"application/dash+xml; codecs=xyz",
"application/dash+xml; codecs=xyz,vorbis",
"application/dash+xml; codecs=vorbis,xyz",
"application/dash+xml; codecs=xyz,vp8.0",
"application/dash+xml; codecs=vp8.0,xyz",
"video/ogg",
"audio/ogg",
"application/ogg",
"audio/ogg; codecs=vorbis",
"video/ogg; codecs=vorbis",
"video/ogg; codecs=vorbis,theora",
"video/ogg; codecs=\"vorbis, theora\"",
"video/ogg; codecs=theora",
"audio/ogg; codecs=opus",
"audio/ogg; codecs=opus",
"video/ogg; codecs=xyz",
"video/ogg; codecs=xyz,vorbis",
"video/ogg; codecs=vorbis,xyz",
"audio/wave",
"audio/wav",
"audio/x-wav",
"audio/x-pn-wav",
"audio/wave; codecs=",
"audio/wave; codecs=1",
"audio/wave; codecs=6",
"audio/wave; codecs=7",
"audio/wave; codecs=",
"audio/wave; codecs=\"\"",
"audio/wave; codecs=0",
"audio/wave; codecs=2",
"audio/wave; codecs=xyz,1",
"audio/wave; codecs=1,xyz",
"audio/wave; codecs=\"xyz, 1\"",
"audio/wave; codecs=\"0, 1,\"",
"video/webm",
"audio/webm",
"video/webm; codecs=xyz",
"video/webm; codecs=xyz,vorbis",
"video/webm; codecs=vorbis,xyz",
"video/mp4; codecs=\"a,b\"; width=1024; Height=768; FrameRate=60; BITRATE=100000",
"Message/Partial; number=2; total=3; id=\"[email protected]\"",
"video/mp4",
"video/x-m4v",
"audio/mp4",
"audio/x-m4a",
"audio/aac",
"audio/aacp",
"video/mp4; codecs=\"avc1.42E01E, mp4a.40.2\"",
"video/mp4; codecs=\"avc1.42E01E, mp3\"",
"video/mp4; codecs=\"avc1.42001E, mp4a.40.2\"",
"video/mp4; codecs=\"avc1.58A01E, mp4a.40.2\"",
"video/mp4; codecs=\"avc1.4D401E, mp4a.40.2\"",
"video/mp4; codecs=\"avc1.4D401F, mp4a.40.2\"",
"video/mp4; codecs=\"avc1.4D4028, mp4a.40.2\"",
"video/mp4; codecs=\"avc1.64001E, mp4a.40.2\"",
"video/mp4; codecs=\"avc1.64001F, mp4a.40.2\"",
"video/mp4; codecs=\"avc1.42E01E\"",
"video/mp4; codecs=\"avc1.42001E\"",
"video/mp4; codecs=\"avc1.58A01E\"",
"video/mp4; codecs=\"avc1.4D401E\"",
"video/mp4; codecs=\"avc1.64001F\"",
"audio/mp4; codecs=\"mp4a.40.2\"",
"audio/mp4; codecs=mp4a.40.2",
"audio/x-m4a; codecs=\"mp4a.40.2\"",
"audio/x-m4a; codecs=mp4a.40.2",
"audio/mp4; codecs=\"mp4a.40.5\"",
"audio/mp4; codecs=mp4a.40.5",
"audio/x-m4a; codecs=\"mp4a.40.5\"",
"audio/x-m4a; codecs=mp4a.40.5",
"audio/mp4; codecs=\"mp4a.40.29\"",
"audio/mp4; codecs=\"opus\"",
"audio/mp4; codecs=opus",
"audio/mp4; codecs=\"flac\"",
"audio/mp4; codecs=flac",
"audio/mpeg",
"audio/mp3",
"audio/mpeg; codecs=\"mp3\"",
"audio/mpeg; codecs=mp3",
"audio/mp3; codecs=\"mp3\"",
"audio/mp3; codecs=mp3",
"video/mp4; codecs=vp9",
"video/mp4; codecs=\"vp9\"",
"video/mp4; codecs=\"vp9.0\"",
"audio/m4a",
"video/m4v",
"audio/mp4; codecs=\"mp4a.40.2,\"",
];
for test_case in test_cases.iter() {
match Mime::from_str(test_case) {
Ok(_) => (),
Err(_) => println!("{}", test_case),
};
}
}
Per https://mimesniff.spec.whatwg.org/#parse-a-mime-type it ignores the invalid parameters instead of failing to parse the mime type.
mime 0.2 did the right thing but mime 0.3 returns Err(FromStrError { inner: MissingEqual })
According to https://tools.ietf.org/html/rfc4329, "application/javascript" is preferred over "text/javascript".
It would seem handy to have this as a common type / constant.
At least this algorithm require to change the parameters present in a MIME type.
Comparing "text/event-stream;".parse().unwrap()
with TEXT_EVENT_STREAM
yields false
. That seems like a bug in this crate to me.
I’d like to parse a Mime
value from a string according to the algorithm at https://mimesniff.spec.whatwg.org/#parsing-a-mime-type. (Test cases in JSON are available at https://github.com/w3c/web-platform-tests/tree/master/fetch/data-urls.) I can implement that algorithm outside of this crate, but then the only way to construct an arbitrary Mime
value seems to be the FromStr
impl (which has its own, different parsing algorithm).
Would you consider adding some APIs to construct a Mime
from its components? Maybe something like:
impl Mime {
fn new(type_: &str, subtype: &str) -> Self { … } // Or Result<Self, …>?
fn add_param(&mut self, key: &str, value: &str) { … } // Or -> Result<(), …>?
}
Alternatively, what do you think of adding this parsing algorithm to the mime
crate itself?
For context: I’m implementing the Fetch Standard’s specification for how to parse/process data:
URLs. On a high level, this is a fallible conversion from &str
to (Mime, Vec<u8>)
. Using the same Mime
type as Hyper would make things easier for code that wants to support both data:
and http:
URLs.
Didn't see an issue tracked for this. Was going to try and fix this this weekend.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.