

How RESTful is Your API? - housecor
http://www.bitnative.com/2012/08/26/how-restful-is-your-api/

======
chime
I've written probably half a dozen unrelated apps that call REST APIs and I
think they all implemented REST differently. Some treat PUT as insert while
POST as update. Some treat POST as insert, PUT as insert/update. Some return
201 when insert was successful, some return 200 whenever anything is
successful. Some issue tokens, some authenticate using headers.

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...](https://trello.com/docs/api/card/index.html#put-1-cards-card-id-or-
shortlink) ), 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.

~~~
alexchamberlain
"POST is insert - PUT is update" is the norm and HTTP compliant way of doing
things. Why not reach out to Trello and ask why you can't do the due-date on
POST?

~~~
arethuza
Unfortunately, I don't think the POST vs. PUT distinction is quite that simple
- PUT is often used to create/insert if you are sending all the data required
to create the new object as part of the 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.

~~~
vidarh
PUT should be idempotent and addressed at the location of the resource to be
created / updated. e.g /books/[isbn], while POST should be addressed at the
location of the _collection_ and give the location of the new resource or an
error. e.g. POST to /books to create a new book entry.

~~~
seancribbs
That's still an oversimplification. POST only implies that the request is NOT
idempotent, and that the request body is submitted to the origin server for
"processing". Consider for example, resources that search for other resources
via information in the request body and redirect to them. There's nothing
wrong with this pattern, and in fact it works nicely for rapidly-changing
server-side information since caching the result of a POST is not allowed.

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.

~~~
w0utert
> 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.

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.

------
regularfry
I'm surprised nobody has mentioned the Richardson Maturity Model:
[http://martinfowler.com/articles/richardsonMaturityModel.htm...](http://martinfowler.com/articles/richardsonMaturityModel.html).
It's explicitly for discussing and characterising the degree of RESTfulness of
a given API.

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.

~~~
davedx
I hadn't seen it before, but I like it. Practical and specific. I think you
could actually use this when proposing time/cost estimates for web service
development.

------
ljd
There is much ado in the REST world about whether one API is more restful than
another. For us, our REST API was designed from our experience as consumers of
other REST API's. Our whole philosophy wasn't about what was true-rest but
rather, what was both consistent and easy to learn.

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.

------
Natsu
> Why Deviate? > Although REST prescribes using HTTP GET, PUT, POST, and
> DELETE verbs for CRUD operations, some clients can’t generate the less
> common PUT and DELETE requests. In addition, some overzealous firewalls
> block PUT and POST. Thus, some RESTful APIs accept all requests via HTTP GET
> and place the HTTP verb in the querystring. For example, to delete user 124,
> the GET request would be for the following URI: /users/124?method=delete
> This technique is especially common in Ruby circles. Another benefit of this
> approach is all requests can be easily generated and manipulated in the
> address line of any browser.

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.

~~~
tomchristie
Overloading the request method using URL paramaters, as the author mentions is
a bad idea. What _is_ accepted behavior, is overloading the request method
using hidden form data in a POST request.

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.

~~~
Natsu
This I agree with. But that comes a lot closer to honoring the semantics of
the HTTP verbs, too. I do understand the need to be flexible sometimes,
especially when some things aren't well-supported, but I cringe whenever I see
GET requests changing application state.

------
deno
> Notice what this doesn’t include? XML and JSON. Neither offers a native way
> to convey a hyperlink.

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>

[2] <http://json-schema.org/>

[3] urn:ietf:rfc:2068 (<https://tools.ietf.org/html/rfc2068#section-19.6.2.4>)

------
pbreit
I found the cheat sheet annoying. Doing all requests over GET is not
acceptable, especially deletes. The jury is still out on GET/POST vs
GET/POST/PUT/DELETE. I don't see any problem with file extensions. After all,
that's how the web has worked from the very beginning. Hard to do discovery
without any guidance on format. Version numbers are not very RESTful and I
don't care for them. Spend a little extra design energy to avoid the need for
versioning. Static URLs are sort of necessary absent better discovery
mechanisms. He skips the notion of returning a resource address as a
"Location" upon creation.

~~~
jcdavis
Annoying or not, its a fairly accurate description of the state of APIs. I
agree about the all GET setup, although I've never actually seen that in the
wild (seems pretty dangerous). I personally have no problem with using POST
for all endpoints with side effects, though opinions certainly differ there.

------
davedx
Dramatic, and makes broad unsubstantiated claims about API's "in the wild",
but the details are right. His most important point that we as API writers can
work on is the "discovery" part. Hardly anyone is doing HATEOAS [1]. I think
the reason for this is that if you write a public API, you're going to
document it well (or nobody will use it), and good documentation kind of
alleviates the need for in-service discovery.

[1] <http://en.wikipedia.org/wiki/HATEOAS>

~~~
csulok
In service discovery is just convenient. With SOAP libraries, using a web
service is as easy as 2-3 lines of code. The library handles loading the wsdl
file, generating functions with appropriate parameters, sending requests and
parsing response and exception handling. Without this ability, it's a lot more
code.

It's not necessarily harder, but it's more code nevertheless.

~~~
gizzlon
The problem with SOAP + WDSL was just that it was overly complex and, in my
experience, never worked cross-platform & cross-language. And since it was so
complex it was "¤%& impossible to debug at lower levels. Argh! I hate soap
with such a vengeance it's actually embarrassing.

~~~
coopernurse
Agreed. These problems (complex tooling, poor interop, non-human readable
WSDL) were my motivation for writing Barrister RPC (a JSON-RPC implementation
with a human readable IDL).

For those who find value in separating interface from implementation, you
might take a gander.

<http://barrister.bitmechanic.com/>

------
sopooneo
The big question I almost never see addressed: Why would true REST be worth
pursuing anyway? What's so good about it over other ways of setting up APIs?

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.

------
fideloper
This is very interesting. The idea and requirement between ease of use and
full-REST implementation is definitely worth discussing.

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?

------
regularfry
Having spent a while now working on a project with a RESTish API, I can say
that I'm _really_ regretting not pushing harder for hypermedia controls
earlier. It would have made pushing upgrades out a lot simpler.

~~~
shimonamit
Easier for you, that is. The problem with HATEOAS is that it requires
commitment on both parties (server and client) to that convention. For the
client developer that means no hard coding changing URLs. But they will, and
you'll be to blame when your server changes break their code. You'll say "but
you didn't HATEOAS" and they'll say "my app is broken, fix your API now" and
you... who wants to go there?

~~~
regularfry
In this case we're in control of the server and the client, so it's less of an
issue, but in general it's not the ability to change URLs that I'm getting at
here, and that's not a flexibility we've needed. It's the ability to add extra
functionality by adding links on each resource without breaking existing
clients that I'm missing at the moment.

~~~
shimonamit
Adding HATEOAS resource links should not break client code. It is nothing more
than adding an attribute or sub-element to your xml.

~~~
regularfry
Precisely.

------
lucisferre
This is an excellent and insightful overview of REST both the good and the
bad. It's the Hypermedia API problems that stand out the most to me here. It's
definitely the unicorn of the whole thing.

------
njharman
The accept header seems natural place for versions.

oh and tacks not tax <http://en.wikipedia.org/wiki/Brass_Tacks>

------
jakejake
I spent decent amount of time and effort making my code generator/framework
create a proper RESTful API, but I have to admit it is a bit tricky to figure
out what is actually "proper." I feel like I was able to do a decent job with
everything except the discovery service. If any PHP devs would like to
contribute or just look at the API please feel free at phreeze.com

------
cwp
Interesting. He gives three examples of truly RESTful APIs, and Tim Bray was
involved in creating two of them.

------
rickmode
The web page is unreadable on my iPhone. Right side is clipped; same as
another post says about Android.

~~~
housecor
Thanks for the heads up! Fixed.

------
dwood
I once asked Tim Berners-Lee about POST vs. PUT and he told me that POST was
for insert (as in posting a nntp article) and PUT was for update. That's good
enough for me.

------
andrewdotnich
s/tenant/tenet/g

~~~
idan
This.

~~~
peterwwillis
...is not Reddit. Stop that.

------
bmunro
Off topic, but the right side of the paragraph is cut off on Android.

~~~
housecor
Thanks, fixed.

