Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Hypermedia APIs on Rails (stateless.co)
39 points by AffableSpatula on Dec 20, 2012 | hide | past | favorite | 18 comments


The convention that Django REST Framework (which is an add-on for Django, not part of the core) uses is to add a 'url' attribute to each resource to represent the cannonical id.

Even better, when you hit the API with a browser, you can click around and explore the links easily:

http://restframework.herokuapp.com/users/

The docs talk about it a bit here:

http://django-rest-framework.org/tutorial/5-relationships-an...


I like to take this one step further and return referenced objects with both their ID and their URL as actual objects instead of strings. This is incredibly helpful for working with the API in something like Backbone.js, because then there's no need for logic in determining if it is getting a list of IDs as strings or full objects. It's doubly helpful if the references are to objects of different types. The client simply loads the objects as given, and can do a sync if it's missing attributes it expects. (Of course, sending the full data in one request is usually preferable.) Also, the `url` property on the model just returns the `url` attribute instead of needing to duplicate the URL construction pattern.

So,

    …
    {
        'id': 123,
        'url': '/resource/123'
    },
    …
instead of

    …
    '/resource/123',
    '/resource/124',
    …
or worse

    …
    123,
    124,
    …
Also, Django REST Framework is easily my favorite REST API tool for Django. It's very straightforward to use just as much or just as little of it as necessary. In fact, it's powering the main views of the upcoming second draft of http://marquee.by (the entire site is effectively a browsable API).


...I came up with a simple media type that adds linking on top of JSON

Adding hypermedia reflection to JSON does amazing things to APIs. We've been doing this via oData for awhile, and it makes things so much easier on the client. Anyone building a hypermedia/REST API with JSON (or XML) would make good of using standard formats that incorporate this functionality and attitude.


This doesn't need to be a Rails feature. Rails is for building web apps. There is a whole bunch of extra stuff Rails does that a web api doesn't need to care about. So, it really doesn't need to be a mvc web app framework feature.

Also, why tie this idea to Rails at all? Why not just make your own plugin or Sinatra app or frameowrk or whatever?


Because rails is used for building APIs, linking is a good practice, and there's no need to reinvent the linking/embedding wheel every time you create an API.

Rails has API defaults which should include sensible linking defaults we can build tooling around.


hence rails-api


I blogged about this same idea in response to a different article 3 months ago. Seems like the hypermedia discussion keeps coming up. Here's my response article: http://rtigger.com/blog/2012/08/27/discovering-the-value-in-...

TL;DR - there's no value in discoverable (hypermedia) APIs short of some generic API browser that end users don't really want.


There are a benefits, but most people won't notice them without first actually using a hypermedia API.

* It's self-documenting. Client developers can find all the endpoints just by clicking around (instead of reading mountains of docs).

* Client apps don't need to keep a list of hard-coded urls for random access, removing one of the most brittle parts of client apps (they should know about rels of course, but those end up being easier to keep track of).

Once you actually use an API like this, other APIs feel like they're in the stone age and how to do things with them seems like a continual guessing game. And it's still simple as hell -- remember it's just json with links. It's not like that requires a lot of extra effort.


Fair enough - I haven't actually used a hypermedia API (short of OData). I really can't see the documenting point though. Sure, you get a list of actions that you can perform, but you get those in a response object. Some people compare this to "intellisense documentation", but really it's more like having to decompile the library to figure out what's going on. You have to do something extra in order to figure out what the next step is, rather than just having it available. Also, I'm pretty sure any API that is currently "discoverable" probably also has a full suite of documentation. Why do the same thing twice?

Not sure about other languages, but most of the client apps I make don't use hardcoded urls - they use a base API url, and then modifications for specific resources. The RestSharp library for C# is a great example of how this works, and even in javascript it's not hard to refactor things so they use a base url and append path & parameters based on the models you're working with.

I'm not arguing the simplicity of it, although it would be more simple to implement if we agreed on a standard like in the original article. I'm just arguing the value.


You lept to a conclusion here:

> I think the original idea behind discoverability was that you could have a “RESTful client” that could in theory work with any REST service that implemented discoverability.

Your analysis of that conclusion makes sense (a generic API browser is not very useful), but why did you think that's "the original idea behind discoverability"?

The BitNative article you link to gives the reason that is usually cited for using hypermedia:

> This allows the API to be highly evolvable because it avoids creating a coupling between the client and the server.

Even more important IMO is that it makes it easier for the many different parties to serve the same API.


I don't understand the coupling aspect. You're moving from one dependency (URIs) to another (implementation of discoverability). Until HATEOAS/discoverability/rest links themselves are a standard, you're just binding to the way that API decided to do it. And that in my mind is a much bigger dependency than a URI string.


The coupling is removed because you both standardize on the message format: the media type.

Think RSS: clients and servers are decoupled.


While the library that browses arbitrary restful apis has to be generic, the applications built with that library, intending to interact with a specific API don't have to be generic


I suppose that's a good point. Once we have a standard in place (like the one proposed in the original article) it'd be relatively easy to make a client library that standardizes access to those kinds of API. You know, like WSDL used to do.


Isn't this what the Link header is for? Why put them in the JSON?

The only reason I'm aware of is for compatibility with JSONP. Github's API normally uses Link headers, but adds a "meta" object for JSONP requests: http://developer.github.com/v3/#json-p-callbacks


For those of us not quite as embedded in the bubble as this author, what's this in response to?


It's in response to Rails being on the trailing edge of Hypermedia/REST API design, and not making moves to pull ahead. Rails's strength is in its sane and powerful defaults; the absence of a sufficiently sane and powerful default for API construction is a hindrance (especially now that ActiveResource is getting booted from core Rails).

DHH has simply never taken REST/Hypermedia seriously as a design philosophy. He, and Rails, have been content to move simple JSON serializations over the wire and leave it at that. This was good enough a few years ago, but is getting to the end of the runway for the present and future.


nothing specifically. it's an attempt to articulate why making hypermedia APIs the default is a good idea for Rails, in terms that someone like DHH can't just dismiss as "wankery".




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: