How RESTful is Your API?
bitnative.com
bitnative.com
Just last night I wrote some code to auto-create Trello cards and assign them to a specific list. The https://trello.com/docs/ seem fairly decent but what they don't tell you is that POST is insert, PUT is update. Moreover, while you can assign a due date via PUT ( https://trello.com/docs/api/card/index.html#put-1-cards-card... ), you cannot assign one via POST ( https://trello.com/docs/api/card/index.html#post-1-cards ). So if you want to create a card with a due date, you have to POST, read ID, then PUT the due date to /card/id.
The problem with people trying to be RESTful is that they pay too much attention to stuff that doesn't matter (71 status codes) instead of stuff that really matters (simplify complex insert/update). I'd rather have Trello return 400 on errors and provide a text description than use one of the 30+ 4xx errors. And I'd rather have them accept due date when inserting a card. Trying to conform to REST's standards is like trying to be XHTML compliant. Great, your site validates. But you're still using white font on yellow background!
Be as RESTful as you need to be. But more than that, be useful and sensible. Don't make me call your server six times to make one valid GET request.
NB Personally I thought this use of PUT was splitting hairs when I first started reading about RESTful interfaces but having used a few and written one RESTful service it does rather make sense.
The core problem in my mind, is not whether one should insert or update on PUT/POST, but whether one should even be considering HTTP-based APIs to be gateways to what amounts to a database. The domain concepts in the application might not map directly to a resource-centric design, and that's ok. When you focus on the resources, their behavior, and hypermedia, then you "get" REST. If your application isn't shaped like HTTP/REST, then maybe it shouldn't try to be.
I think it's widely recognized that you shouldn't consider making your REST API a direct gateway to a database. For one, it's potentially very dangerous, but it is also limiting the design of your API, because typical databases basically have no way to insert anything besides rows of data with fixed columns (relational) or raw untyped data (NoSQL).
I think the 'purest' form of REST API's for creating and updating is that PUT should be idempotent and used for existing resources addressed by an existing URI, while POST can basically create resources any way it sees fit, and return the URI of the new resource. This allows doing a POST followed by a PUT to create and initialize a resource, without having to know how and where the resource will be created, and without requiring to set each and every attribute of the resource with the POST request.
bitter? me? nah
For my money there's nothing actually wrong with implementing, say, a level 1 API, as long as you don't claim anything higher. It'd be very nice for everyone to be at level 3, but obviously the tooling isn't there yet to support it universally.
We do fancy stuff like send back HTTP codes that aren't always invited to the cool HTTP code parties like, "Payment Required" and we used "Accepted" on a PUT (Update).
Also, while we know that a rest API should be entirely self documenting we found it more practical to create a GitHub account explaining every call with sample code in variety of languages, all doing the same thing: sending JSON via a REST library.
We are a B2B product and reducing any barriers to enriching our clients is a must. We've worked on big dev teams and understand that if we want our product to get on the next sprint we need to make sure that they can copy and paste our code into their software and it'll work. It's just the nuts and bolts of business.
I would accept data on floppy disk duct taped to carrier pigeons if that was the easiest way for clients to interact with our algorithms. Fortunately for us, being "pretty" rest-y was a better fit for everyone.
This is a very bad idea for something like delete. It's Daily WTF material:
http://thedailywtf.com/Articles/The_Spider_of_Doom.aspx
Any firewall that blocks POST requests but not GET is a WTF in and of itself, for that matter.
The later is what Rails actually does - http://guides.rubyonrails.org/form_helpers.html section 2.4
"There are two noncontroversial uses for overloaded POST. The first is to simulate HTTP's uniform interface for clients like web browsers that don't support PUT or DELETE" - RESTful Web Services, Leonard Richardson & Sam Ruby.
Both XML and JSON offer standard ways to include hyperlinks. XLink[1] and JSON Schema[2], respectively. Not to mention you can include hyperlinks in headers[3].
The problem with “hypermedia” is that the concept is completely useless without common nouns and verbs. So it’s fine if you can fit your application to use WebDav or AtomPub plus extensions, but for a custom API there’s no point.
[1] https://en.wikipedia.org/wiki/XLink
[3] urn:ietf:rfc:2068 (https://tools.ietf.org/html/rfc2068#section-19.6.2.4)
Content-negotiation is what people should use to specify format.
It's not necessarily harder, but it's more code nevertheless.
For those who find value in separating interface from implementation, you might take a gander.
Write the client to use new actions without needing an update? Impossible.
Output the list of available actions using <link rel="..."> rather than some domain-specific tag? What do I ever gain from this other than bloating my API and making it harder to read?
If I recall correctly, Fielding himself says that it may be detrimental to an individual organization in the short term, but if we all do it, it will eventually help make our APIs collectively interoparable.
Two Points: * Consistency could be very useful across web-services * Simplicity is exceptionally important
If all API's were created with a 'full-REST implementation', that would comply with the need (Desire?) for consistency, however it would not necessarily be easier.
What might be "hard": * Some limitations (firewalls, lack of knowledge) on PUT and DELETE * The debate on when to use PUT and DELETE * Editing headers to request content type (xml vs json etc)
So the big question seems to be: What is the mix between consistency and ease of use?
Perhaps we can be full-on REST but then make it easier with code libraries?
oh and tacks not tax http://en.wikipedia.org/wiki/Brass_Tacks