oEmbed FAIL! Represent RESTfully.

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.

Trackbacks

lucasjosh.com » Blog Archive » Links Links Links
writes:
May 12, 2008 at 11:07 PM

[...] oEmbed FAIL! Represent RESTfully [...]

IM2 | OQP » Microblogues, ou pourquoi se brosser les dents en public
writes:
June 11, 2008 at 5:00 PM

[...] au moins le header Content-Type qui permet de demander au serveur la représentation voulue. Bref, OEmbed fails REST.Un avantage à tout ce réseautage, c’est une amélioration significative du signal par [...]

Comments

Mike Malone
says:
May 9, 2008 at 4:32 PM

Hey Jared,

Great post I usually find the REST-bigots a bit annoying, but you do have a point. Pragmatically, though, it’s easier to get people to implement something that requires a single endpoint with a simple API vs. asking people to look at HTTP headers and “do the right thing.”

In the end, the spec is worthless if people don’t implement it. And it’s more valuable for consumers than it is for providers. The trick, from the beginning, has been to write something that providers will implement. It’s easier and less risky for providers to stick a single, simple endpoint somewhere that does these conversions. With a RESTful implementation like yours they’d have to make a change to their codebase, which would require more justification. Also, while this is fairly straightforward to implement for static pages, it’s somewhat of a PITA for static resources.

I just sent this post to Richard Crowley (who helped put together the draft spec along with Leah, Cal and I), and he pointed out that most templating systems can’t handle this. They’re not capable of responding differently based on an HTTP header.

So… great idea, we’ll keep it in mind, but I have mixed feelings.

Jared Hanson
says:
May 9, 2008 at 5:03 PM

Mike,

Thanks for the reply. You’re mention of static pages and templating systems that don’t allow inspection of HTTP headers does give some justification to oEmbed as specified.

However, you could just tack on some additional query parameters as a work around for poor templating systems. For example,
flickr.com/photos/bees/2362225867/?format=oembed
It’s not ideal, and would still require modification to the codebase, as you mention.

One potential use, that seems reasonable to me, would be oEmbed translators implemented by third parties and hosted on a different domain than the original resource.

I realize its not specified yet, but I do have some concerns about the forthcoming discovery mechanism.

If XRDS (or similar) is used, will every user submitted link go through oEmbed discovery? Would the discovery process trigger an HTTP request to the original resource? In all likelihood, that request will fail to discover the oEmbed API endpoint, due to most resources not implementing support. This seems wasteful as it utilizes additional bandwidth and induces additional load on the host.

One workaround would be to send discovery requests to the root domain, regardless of the depth of the resource. For example, any Flickr URL just sends discovery requests to flickr.com. The response can be cached and reused for any URL hosted at the flickr.com domain.

Even then, however, implementing support for discovery puts you back in the same position of modifying the codebase, in order to respond with an HTTP header or HTML meta tag. Of course, depending on how discovery is scoped, the changes may be minimal.

As always, trade offs abound. Keep my notes in mind, and if you want feedback on further revisions to the spec, I’d be happy to give my opinion.

Mike Malone
says:
May 9, 2008 at 5:10 PM

We’ve done a bit of work on discovery, and you can read the draft spec we put together at http://oembed.com/draft.htm

It’s based on the robots.txt concept. A global config file at the root of the domain. There are definitely tradeoffs to doing it this way, but again, it seemed to be the simplest approach that would be the easiest for providers to implement. We talked about doing something like Facebook share, where you put a link tag in the HTML document. But, again, that would require a global change to the codebase, and wouldn’t work for non-HTML content.

I bumped into Chris Messina yesterday and talked to him for a bit about OEmbed. He suggested that I look into XRDS too. Honestly, I hadn’t heard of it before then. I’ll go read that spec now.

If you’re interested in following the spec as it develops, and contributing any ideas you might have, feel free to join our Google group at http://groups.google.com/group/oembed.

Vitorio Miliano
says:
May 10, 2008 at 11:15 AM

A good writeup. You posted this just a few hours before I finished writing up a more RESTful alternative myself, which should be linked to by my name.

Rather than specify a custom content type, you can use parameters. You can even specify version this way:

Accept: application/json;oEmbed=1.0

Service discovery can work an HTTP way, too. HEAD requests to specific resources are designed to provide this sort of information without requiring downloading large quantities of content:

Alternates: {”" 0.0 {type application/json} {x-oEmbed 1.0}}, {”" 0.0 {type text/xml} {x-oEmbed 1.0}}

I don’t think the template argument is the right one. No-one’s writing static templates by hand and using them in isolation; they’re parsed by servers and services that can handle parsing HTTP headers. A WordPress (or equivalent) plugin does all the work for you anyway.

Manuel Simoni
says:
May 11, 2008 at 2:41 PM

Great idea, way to go!

However, I am so enamourmed with oEmbed in general, that I just want the service to succeed and am willing to accept a less than perfect implementation :)

Tamlyn
says:
May 12, 2008 at 5:33 AM

Good discussion. It’s addressed some of my initial concerns with the standard.

@Mike, may I suggest you add a little paragraph to oembed.com explaining why you chose to do it in this way (easy of implementation with static resources, templating systems, existing codebases etc.)? It might save you having to repeatedly justify yourself to folks like us :)

Stephen Paul Weber
says:
May 14, 2008 at 9:22 AM

I must say that I dislike oEmbed more because they’ve invented a new metadata format that we didn’t need… all that data can be represented in other ways (microformats or media RSS) already…

Colin Devroe
says:
May 19, 2008 at 6:09 AM

Jared: In my opinion this is a great suggestion. In fact, I think I’ll work up a ticket that Viddler support this way in addition to the way we’ve already put into place.

Stephen: The main problem with what you are describing is that we wanted to avoid the need to gather the entire document. Though I agree this could have been built ontop of other standards.

Thanks for your feedback everyone – working together like this in a conversational way can only make things better.

Niklas Lindström
says:
September 27, 2008 at 9:27 AM

I agree with the criticism regarding the lack of RESTfulness and defining a new metadata carrier. I think oEmbed would work very well as an extension element in Atom Entry documents (who already have most of the properties oEmbed (re-)defines). Or by reusing (in such atom entry docs) e.g. Media RSS, as Stephen Weber suggested.

Granted, if (as I and so many others hope) RESTfulness and Atom permeation on the web becomes much more well established (approaching ubiquity), this would be dead easy to define further down the line. (Albeit not having done it initially maintains the fragmented web data infrastructure, already in dire need of unification.)

(Now, on to building a bridge from Atom to RDF for the 3.0 web. :) Best regards.)

Nicolas
says:
September 14, 2009 at 9:54 AM

@Mike Malone: a global config file at the domain root?!? Why do you keep following EVERY “don’t do this” recommendation backwards? robots.txt is an abomination.

Post a comment