oEmbed is the latest standard to come out of the Web 2.0 developer crowd. While I’m typically a huge advocate of standards, and think much of the prior work has been superb, oEmbed fails on almost every level. So much so, in fact, that I’m writing this post to declare it worthless, and suggest an alternative.
Upon first seeing the spec, I immediately tweeted:
oEmbed completely ignores REST principles. GET with a Content-Type to the original resource. Benefit: a single URL per resource. C’mon!
Allow me to further explain…
To begin with, let’s dive into the specification, and take note of the things that immediately raise red flags.
An oEmbed exchange occurs between a consumer and a provider. A consumer wishes to show an embedded representation of a third party resource on their own web site, such as a photo or an embedded video. A provider implements the oEmbed API to allow consumers to fetch that representation.
Hmm… that sounds suspiciously like an HTTP GET request. Why the need to refer to this as “the oEmbed API”?!? Something suspect must be about to go down.
Configuration for oEmbed is very simple. Providers must specify one or more URL scheme and API endpoint pairs. The URL scheme describes which URLs provided by the service may have an embedded representation. The API endpoint describes where the consumer may request representations for those URLs.
Wait… what? This oEmbed thing requires two URLs to fetch different representations of the same resource? Have we not learned even the most rudimentary REST principles in the past few years? Here’s a quick lesson: a single resource can have multiple representations. One URL, multiple data formats. Once that is understood, the need for an oEmbed API endpoint drops away entirely.
Even so, let’s be pragmatic and use oEmbed, since some respectable providers have already implemented support for it. (Which begs further questions, but I’ll let that slide.) To start, we need to get the address of the API endpoint. That mechanism is not specified, so we’ll have to resort to hardcoding endpoints. XRDS could be useful here, but that introduces further complications. Besides, there is better way.
oEmbed with REST to the Rescue!
Since the URL to the original resource must be known, and an oEmbed representation is desired, the oEmbed API endpoint is completely unnecessary. Just request the oEmbed representation from the resource directly.
GET /photos/bees/2362225867/ HTTP/1.1
Host: flickr.com
Accept: application/oembed+xml
Flickr could then respond with our embed-ready resource.
HTTP/1.x 200 OK
Content-Type: application/oembed+xml
<oembed>
<version>1.0</version>
<type>photo</type>
<title>Bacon Lollys</title>
<author_name>bees</author_name>
<author_url>http://www.flickr.com/photos/bees/</author_url>
<cache_age>3600</cache_age>
<provider_name>Flickr</provider_name>
<provider_url>http://www.flickr.com/</provider_url>
<width>500</width>
<height>375</height>
<url>http://farm4.static.flickr.com/3040/2362225867_4a87ab8baf.jpg</url>
</oembed>
See that! There is absolutely zero requirement for the oEmbed API. All we need to do is define a couple data formats and the associated MIME types. While there is evidence of duplicative effort, the oEmbed formats look reasonable and have both XML and JSON output. I propose we define them as application/oembed+xml and application/oembed+json.
Error handling is equally trivial. If support for RESTful oEmbed is not implemented, a standard HTTP 406 Not Acceptable status code would be returned to the client. The client could then fail over to screen scraping or proprietary APIs as necessary.
I hope I’ve outlined my case against oEmbed effectively. If anyone has any questions or concerns, drop a line in the comments.
