GithubHelp home page GithubHelp logo

mime's People

Contributors

abonander avatar bluejekyll avatar cyderize avatar frewsxcv avatar fugangqiang avatar globin avatar golddranks avatar j16r avatar jgillich avatar jim-holmstroem avatar jimmycuadra avatar kaj avatar kornelski avatar markjr94 avatar mathiaslengler avatar matklad avatar mikedilger avatar mr4x avatar nox avatar pftbest avatar reem avatar retep998 avatar rustonaut avatar s-panferov avatar seanmonstar avatar sfackler avatar simonsapin avatar tetsuharuohzeki avatar tomprince avatar withoutboats avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mime's Issues

Distinguish MIME types from MIME patterns

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-ranges? 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.

Failed to parse multipart/form-data boundary

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)

mime/src/parse.rs

Lines 131 to 132 in fda8cf1

Some((i, c)) if i == start && is_restricted_name_first_char(c) => (),
Some((i, c)) if i > start && is_restricted_name_char(c) => (),

feature: Consuming constructor

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?

#21 breaks mime! / Mime type

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.

release request

Can I get a release w/ the serde support for my downstream crate formdata?

Handling quoted-string parameter values correctly

Parameter values can be quoted strings which:

  1. can be empty (currently rejected)
  2. can contain escape sequences (e.g. \") (currently rejected)
    handle escape sequences correctly

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:

  1. remove Name::is_str (or better have Name for names and Value for values and do not have is_str on Value)
  2. introduce 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 quoted
  3. introduce to_content_str(&self) -> Cow<'a, str> which:
    1. returns Borrowed(self.str_repr()) if it's not quoted
    2. returns Borrowed(&self.str_repr()[1..self.str_repr().len()-1]) (+- optimiz) for quoted value not containing escape sequences
    3. returns Owned(unquoteself.str_repr())) which returns the string represented by the quoted-string by undoing any quoting escapes etc.

1.0 Release Discussion / Wishlist

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?

Publish mime 0.2.0

The serde bump is a breaking change and wasn't released on crates.io.

Wrong documentation for STAR_STAR

This is what the constant looks like on the module doc page:

page-shot-2017-8-15 mime - rust

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.

mime 0.3.10 is backwards incompatible and published

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

build and doc-open thwarted due to feature `rename-dependency`

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?

[Question] mime::Mime constructor from 0.2.6 to current version

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.

Charset case may need to be preserved

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.

Serde 0.9

Any chance to get the serde feature updated for serde 0.9?

parsing quoted parameters conflicts with RFC 2045

assert_eq!(mime.param("charset"), Some("\"utf-8\""));

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?

build error after updating rust

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`.

Build error after updating to latest nightly

   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`.

MIMEs with semicolons after quotes fails to parse

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.

Serde feature?

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?

Build broken on 1.15

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?

build error from crate

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.

Cannot use constants as patterns

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

String trait should be implemented for Mime

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.

Can't compile tests with Rust 1.27

+ /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().

Mime.to_string() does not match webidl patterns

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.

Dealing with extended MIME types

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.

No way to create a custom Name value?

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 Mimes 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.

Provide a trait for getting a type's MIME [discussion]

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.

RFC's differ for Media Types depending on context.

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.


Differences:

  • 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

  • in HTTP quoted-strings can contain any char 0x00-0xFF which can be anything including invalid or malformed utf8 (i.e. it can be not representable in rust strings as it add basically arbitrary bytes)
  • in MIME quoted-strings additionally contain any CTL (including DEL/0x7f, except '\t', '\n', '\r' through they could already be contained before, that doesn't change)

[Question] Version discrepency from git repo

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.

Parse failes on MIMEs with multiple values not enclosed in quotes, or empty values

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),
        };
    }
}

Constructor from components, or MIME Sniffing Standard-compatible parser

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.