Sean's Blog

My Development Blog

  Home  |   Contact  |   Syndication    |   Login
  17 Posts | 0 Stories | 96 Comments | 0 Trackbacks

News

Twitter












Archives

.NET Development

For those of you that missed it, Rob Conery offered a challenge a couple nights ago to build an API for Tekpub. In response to this, a few different developers took the opportunity to propose their solution to the requirements. One of those developers, John Sheehan, offered his solution entitled, Don’t build the best REST API, build the best HTTP API and tweeted that the title might be a bit linkbaitish. I understood the point he was trying to make and I think he did a fine job. Building an API should be about building the best API for the job. If you're following an architectural pattern like REST for the sake of following an architectural pattern, I suggest you stop and consider what it is you want your end results to be. For this, I can't argue with John because I agree with him. Having said that, I felt John missed an opportunity to demonstrate HATEOAS principles in a simple post that could have cleared some confusion among newcomers to REST that don't understand what hypermedia really is. John disagreed with me --it's ok, I don't hate him for it. The purpose of his post was to demonstrate how one could build the best API based on Rob specific requirements.

The purpose of this post is to pick up on what I feel is an otherwise great post. Credit goes entirely to John for the original API and JSON results returned from his proposed API.

Wikipedia says, "Hypermedia is a computer-based information retrieval system that enables a user to gain or provide access to texts, audio and video recordings, photographs and computer graphics related to a particular subject." I feel that's rather confusing and not very informative. I'd rather say, "Hypermedia is the embedding of links within responses, which will indicate to a consumer the available resources and state transitions", but even that's confusing. Let's try to explain this with some actual data.

Below is a JSON snip (including a tiny bit of API documentation) from John's blog:

// Request
GET /api/productions/PRCS

// Response
Content-Type: text/json
{
    "id" : "PRRD",
    "name" : "RavenDB",
    "author" : "Oren Eini",
    "last_updated" : 1356976799,
    "episode_count" : 5,
    "channels" : [ "Databases" ],
    "episodes" : [
        {
            "id" : "EP100",
            "title" : "Why You Should Care About RavenDB",
            "duration" : 1200,
            "release_date" : 1356976799
        },
        {
            "id" : "EP101",
            "title" : "Understanding Document Names",
            "duration" : 300,
            "release_date" : 1356976799
        },
        ... truncated ...
    ]
}

As was previously stated, I believe this is a good start, but I wanted to show what this result could have looked like if we added some hypermedia bits to it.

The first thing that should jump out to you if you wanted to consume this data is it requires some working knowledge of the API in order to get additional details about the data. For example, what if you wanted to get an episode document by its unique identifier? You could go to the documentation and hope somebody remembered to add details about where to perform this action. Maybe you'd get lucky and find that information, but what if it moves in the future? The point is, you shouldn't have to worry about these details. The API should be robust and flexible enough to allow consumers to follow "links", much the same as hyperlinks, to the detail it is requesting rather than relying on hard-coded strings to URIs where the resources should be.

Following is an update to the JSON that includes some potential hypermedia bits:

// Request
GET /api/productions/PRCS

// Response
Content-Type: text/json
{
    "id" : "PRRD",
    "author" : {
        "name": "RavenDB",
        "url": "/api/authors/Oren%20Eini"
    },
    "last_updated" : 1356976799,
    "episode_count" : 5,
    "channels" : [ { "url": "/api/channels/Databases" } ],
    "episodes" : [
        {
            "id" : { "url": "/api/episodes/EP100" },
            "title" : "Why You Should Care About RavenDB",
            "duration" : 1200,
            "release_date" : 1356976799
        },
        {
            "id" : { "url": "/api/episodes/EP101" },
            "title" : "Understanding Document Names",
            "duration" : 300,
            "release_date" : 1356976799
        },
        ... truncated ...
    ]
}

And's pretty much it (I made bold the parts I updated)! As you can see, the data provides a URI from which to locate additional details about specific resource types. If those URIs change, the API developer(s) can simply update the URIs with their new location and any consumers can be blissfully unaware of any updates (from a programmatic perspective) because the data explains where to find the additional details.

Often times, without much effort, application developers can improve the future-proof-ness of their API by following simple guidelines. My intent of this post was to demonstrate that with little effort, we are able to add hypermedia bits to a JSON result and extend a simple Web API to do just that. Hopefully, somebody finds it useful.
posted on Sunday, March 4, 2012 12:14 PM

Feedback

# re: Building a RESTful API - A Followup to John Sheehan 3/4/2012 12:28 PM Ryan Cromwell
"author" : { url: "/api/authors/Oren%20Eini",
name: "Oren Eini"
}

This would be much more easily consumed and is what John was suggesting, I believe, in the Hypermedia section of his post.


# re: Building a RESTful API - A Followup to John Sheehan 3/4/2012 1:40 PM Sean Fao
Indeed...that would be a better. Updated...

Post A Comment
Title:
Name:
Email:
Comment:
Verification: