2012-04-18

Even more on the future of MIME Media Types

So I decided to spend some time today seeing if I could flesh out some of the additional details on this hypothetical revamp of MIME Media Types... largely as a thought experiment to see how it would evolve... here's what I've got so far... This is all just public brainstorming at this point so the notes are a bit disjointed and unpolished. Bear with me. Comments and feedback are obviously quite welcome.

All data representation are essentially, at their core, a stream of bytes. Currently, we have the "application/octet-stream" media type that serves as a kind of default baseline for all other media types. If an application does not understand any given media type, it is supposed to fall back to handling it like it would handle "application/octet-stream".  So let's make that our first baseline Content-Profile. We'll call it simply, "octet-stream".

HTTP/1.1 200 OK
Content-Profile: octet-stream


{some set of bytes}

This is exactly equivalent to setting Content-Type: application/octet-stream.

Let's take a step up from there. Let's assume that our stream of bytes represents US-ASCII character data. Let's suppose, for instance, that it's the simple message "Hello World". Today, we would represent this with Content-Type as...

HTTP/1.1 200 OK
Content-Type: text/plain


Hello World

The media type "text/plain" actually defines two distinct components.. "text" which identifies the content as character based and "plain" which identifies the content as having no formatting data or processing instructions what so ever. Let's separate these into distinct Content-Profile tokens... giving us...

HTTP/1.1 200 OK
Content-Profile: octet-stream, text, plain


Hello World

Right away we can see that things can get rather cumbersome with this approach, so let's state that every profile can have zero or more "assumed profiles".. for instance, we'll just say that everything is assumed to be "octet-stream" so we don't really have to declare that part in our Content-Profile field... also, "plain text" is generally considered a reasonable default given the lack of any additional information so let's just say that given...

HTTP/1.1 200 OK
Content-Profile: text


Hello World

... we can safely assume that we're talking about plain text.. the exact equivalent to "text/plain"

Let's throw another wrinkle into the mix. Let's suppose that our plain text is encoded as UTF-16. With media types currently, we have this charset parameter that is used to identify the encoding of character data within the entity. For instance "text/plain;charset=utf-16". My question is... why does it have to be a parameter? Let's just say that character encoding identifiers are are valid Content-Profile labels... therefore, if I want to say that this payload entity is equivalent to "text/plain;charset=utf-16".. I would simply say:

HTTP/1.1 200 OK
Content-Profile: text, utf-16


Hello World

Syntax wise, that's a hell of a lot clearer than "text/plain;charset=utf-16"... so far, so good...

Let's expand on this notion of assumed profiles... it may not make a lot of sense yet, but let's see how it plays out a bit... Right now in the media type registry, there are nine top level media types:

  • application
  • audio
  • example
  • image
  • message
  • model
  • multipart
  • text
  • video
Each of these is further divided into registries of sub-types that inherit properties of the top level type and specify additional semantics on top. Let's define that each of these top level types, and each of their subtypes, will become individual Content-Profile identifiers. For instance, whereas we now have the media type "image/jpeg" to identify jpeg images, with the Content-Profile approach, we would have "image" and "jpeg" as distinct profile identifiers, where "image" is an assumed profile of "jpeg"... Ok, that's clear as mud... Here's the breakdown.. the following are equivalent:
  • Content-Type: image/jpeg
  • Content-Profile: octet-stream, application, image, jpeg
  • Content-Profile: application, image, jpeg
  • Content-Profile: image, jpeg
  • Content-Profile: jpeg
How this breaks down is simple: if we understand what "jpeg" is, we'll understand that it's an image resource.. the "image" profile is assumed. Likewise, we can assume the "application" and "octet-stream" profiles as well... We wouldn't need to write "image/jpeg" all the time, just "jpeg". Of course, if we're using a less well known image format and we're afraid that some application down the line doesn't know how to handle it, then we'd probably want to stick with using "image, jpeg", just to be safe.

Let's look at a more difficult example... MPEG-4 video and audio. In media types, they are identified as "video/mp4" and "audio/mp4"... with Content-Profile, these would be represented as:
  • Content-Profile: video, mp4 or just Content-Profile: mp4
  • Content-Profile: audio, mp4
By default, "video" would be an assumed profile for the "mp4" profile since that's the most common case... which means that unless "audio" is explicitly specified, the application would assume that it's dealing with video/mp4 content.

Let's assume an even more difficult example... multipart media types... currently there are 14 separate multipart subtypes registered within the IANA registry. Each of these would become a distinct profile. For each, there is a requirement that we identify the boundary delimiter and other parameters such as the ID of the starting part, etc.

For instance, let's suppose I have a multipart/related structure. The MIME Media Type would be like: multipart/related; boundary=foo-1; start="<cid:foo>"; type="text/plain"

Assuming "multipart" is an assumed profile of "related", the equivalent Content-Profile would be:
  • Content-Profile: related; boundary=foo-1; start="<cid:foo>"; profile="text"
Now let's get a bit crazy with it... let's assume we're talking about Atom (RFC4287). Right now, the MIME Media Type for Atom is "application/atom+xml". If we need to further differentiate between Entry and Feed documents, it's "application/atom+xml; type=entry" and "application/atom+xml; type=feed", respectively. There's actually four distinct pieces of info in each of those: application, xml, atom and (entry or feed). Let's break each of those out into distinct profile identifiers such that "application" is an assumed profile of "xml" which is an assumed profile of "atom"...

The equivalent of "application/atom+xml; type=entry" would become:
  • Content-Profile: atom, entry
The equivalent of "application/atom+xml; type=feed" would become:
  • Content-Profile: atom, feed
If I was worried that someone who doesn't know about Atom may attempt to process this thing, then I can throw in the "xml" just to be safe...
  • Content-Profile: xml, atom, feed
Oh, suppose we also needed to specify the charset encoding... The equivalent of "application/atom+xml; type=feed; charset=UTF-8" would become, simply:
  • Content-Profile: xml, atom, feed, utf-8
Now let's suppose that I wanted to say that this particular Atom feed conformed to, say, the Atom Activity Streams spec... and let's suppose that's not an IANA registered profile; it's just a spec out there that defines a profile identifier of "http://activitystrea.ms/specs/atom/1.0/"... With Content-Type, there's no way we can currently specify this information without minting a new media type subset of +xml ... with Content-Profile, however, it becomes simply:
  • Content-Profile: xml, atom, feed, utf-8, http://activitystrea.ms/specs/atom/1.0/
This gives us everything I need to know. If I needed to specify additional profiles, I could simply tack them on to the end. I wouldn't even need to register those things. It would be completely decentralized and extensible.

Hmm... looking good so far.. but let's explore it further. MIME Media Types are generally used to associate specific content types with applications capable of handling those types. For instance, within the Android operating system, media types are used to help determine how particular bits of content are to be routed around and handled. In the form of intents. Web browsers can associate applications with specific media types such that when you download a PDF, for instance, it can route the document to an application capable of displaying it, etc. Would we still be able to achieve that same goal with Content-Profile? Essentially: yes, we would. 

Consider this snippet of XML from an Android application's Manifest file:

<intent-filter . . . >
    <data android:mimeType="video/*" android:scheme="http" . . . /> 
    <data android:mimeType="audio/*" android:scheme="http" . . . />
    . . .
</intent-filter>

Note the data elements with the android:mimeType property specifying the MIME Media type ranges... using a Content-Profile as an alternative, this could become:

<intent-filter . . . >
    <data android:profile="video" android:scheme="http" . . . /> 
    <data android:profile="audio" android:scheme="http" . . . />
    . . .
</intent-filter>

The filter would match any type of content using the video or audio profiles. So that works...

Let's look at a another scenario where media types are used... One practical case.. imagine you have an Atom document with a bunch of atom:link elements that use rel="icon". Each link element identifies a different sized icon (perhaps the support all the different options that fancy new ipad retina display requires).. Right now, we'd have this:

<entry>
  <link rel="icon" href=".../img1.png" type="image/png" />
  <link rel="icon" href=".../img2.png" type="image/png" />
  <link rel="icon" href=".../img3.png" type="image/png" /> 
</entry>

Currently, within Atom links and related mechanisms such as the Web Link header, we don't really have a mechanism for differentiating between different sized icons. One option is to register new link relations that identify each size... for instance,

<entry>
  <link rel="icon16" href=".../img1.png" type="image/png" />
  <link rel="icon32" href=".../img2.png" type="image/png" />
  <link rel="icon64" href=".../img3.png" type="image/png" /> 
</entry>

Content-Profile presents another possible option...

<entry>
  <link rel="icon" href=".../img1.png" profile="image,png,icon16" />
  <link rel="icon" href=".../img2.png" profile="image,png,icon32" />
  <link rel="icon" href=".../img3.png" profile="image,png,icon64" /> 
</entry>

Either approach would work in this case... 

For now, I'm going to stop there and pick up the thread again tomorrow...

No comments:

Post a Comment