
Who Cares about GET vs. POST? NoREST - swax
http://swaxblog.tumblr.com/post/112611863175/norest
======
mbleigh
Except that RPC-structured APIs are complete garbage to consume for external
developers because, surprise, they don't know or care what your internal
function names are. And if you aren't thinking about the experience of real or
theoretical third-party developers when building your API, why even have one
at all?

If you ignore HTTP verbs and status codes you're just making it harder for
other developers to grok your system. It's less about adherence to some strict
standard and more about helpful signaling. A GET fetches data, POST creates
new records, PUT is idempotent, DELETE deletes. 4xx status codes indicate a
request error, 5xx indicate a server error. That's all useful information for
someone trying to integrate with your API, but you think that instead everyone
should memorize your in-house conventions. Good luck getting buy-in on that.

The only partial agreement I'd give to this is that I no longer think it's
wise to nest multiple levels of resource IDs (e.g. /customer/123/order/456).
This is, again, out of respect for external developers. Instead, I would have
/customers/123 and /orders/456 (assuming that IDs can't be duplicated between
customers). A flatter URL structure (which is, note, still REST-friendly) can
be an easier-to-consume experience for other devs.

~~~
Udik
Why, are external developers able to consume restful APIs without the need for
any documentation on the system they're talking to? Aren't the various REST
entities (and _all_ the possible links between them, if you're doing HATEOAS)
already part of a protocol the developers of external consumers need to know
beforehand?

~~~
mbleigh
I'm speaking from the experience of a developer who has built numerous public
APIs and client libraries over the years. Yes, you still need documentation
for a REST API (I'm not a HATEOAS utopian), but you can easily attach your
documentation to concepts with which many (probably most) developers are
already familiar.

The article is basically saying "You know how lots of cars have steering
wheels and pedals? Well, I think it's annoying to build cars that way, so I'm
going to use a system of levers and buttons." There's a ton of utility in
anchoring new systems to familiar concepts, and unless you have a good reason
not to you should strive to do so.

~~~
drinchev
I totally agree. That's my first argument against the idea of the OP.

In these days you have out-of-the-box so many already working API clients and
already so many public API End-points that it would be really, really hard to
create some ( opinionated ) better way of doing this.

Libraries like Backbone and platforms like NodeJS ( and many more ) have this
idea so deep that it becomes extremely easy to create an API front-end / back-
end app with just a matter of a couple of files ( even lines ). This is
becoming standard in other platforms as well.

I think the debate is long time shifted from "Is REST good for my app?" to
"How to best follow RESTful principles in my app?"

------
nothrabannosir
_> Why not simplify by removing parameters from the URL altogether?_

Caching. Put a caching proxy in front of your api endpoint and enjoy.

This is the same reason you'll want to do:

    
    
        /api/customer/1234/order/abcd
    

instead of:

    
    
        /api?customer=1234&order=abcd
    

Because even if your cache includes query strings (which it may, and you can
configure it to), you lose order. Now you also have to configure your cache to
ignore ordering on the query string, and that's a lot less obvious (and
probably not even HTTP compliant?).

~~~
spinlock
I feel like the author is advocating for an easy API over a _simple_ API. Yes,
the author's ideas make programming easy. There's less cruft and it's faster
to develop. But, he's loosing simplicity. REST is a simple API because you
don't need things like ordering, etc... That makes it compossible with other
simple technologies (like the caching proxy you mentioned).

------
lmorchard
You have missed the point of REST. REST is an architectural pattern for a
World Wide Web global-scale system. Your API may not fit that description.
Thus, REST may not be appropriate for your API.

Following the REST patterns means you can take advantage of things like
standard agnostic intermediaries for caching & filtering. You can switch or
even spread across service providers by changing domain names in URLs. You can
mitigate network issues through guaranteed idempotence and using conditional
headers like if-none-match. These are all issues that you'll probably have to
rediscover and re-solve on your own, if your API lives long enough.

It is not about SEO or visually "clean" URLs. REST says nothing about that,
despite many misconceptions otherwise. In fact, in a truely RESTful service,
resource URLs can be obscure garbage like
[http://example.com/A13D-DE45-32BC](http://example.com/A13D-DE45-32BC). If
you're using the HATEOS principle, those URLs will be picked up from links in
your responses.

"Pidgeonholing" your errors to standard HTTP error codes means that you've
followed a shared standard, rather than inventing your own from scratch. Also,
4xx errors generally refer to something in the client's request, while 5xx
errors generally mean something has gone wrong while generating a response on
the server side.

If you don't need any of these things - because, say, you're building an API
that will only be used between two parts of your own small system - then don't
worry about REST. Go ahead and build something along RPC lines.

You might regret it someday, if you find yourself needing the scaling
characteristics of the WWW. But, many systems never grow to that point anyway.

------
stupidcar
Pure REST is great for toy examples, where every domain entity fits neatly
into a resource and every operation is a CRUD one that can be represented as
an HTTP verb. So there is a million tutorials explaining how to build a REST
API for a blog with BlogPost and Author resources, or an ordering system with
Customer and Order resources.

However, when you move beyond these simple examples and start trying to build
a REST API for a messy, complex system, you immediately run into trouble. How
do you deal with non-CRUD operations? How do you deal with long running
processes? Or entities in an indeterminate state? How do you aggregate
multiple resources into individual request/responses for performance? How do
you de-duplicate identical entities within an aggregated response? How do you
return only particular fields? How do you handle paging and filtering? How do
you handle transactions? How do you handle authentication and security
restrictions?

All of these things can be solved, but by the time you've finished, your API
will be far from easy to understand. It will need a load of accompanying
documentation to make it usable, and will have a bunch of weird corners where
you're initiating operations as a side effect of setting entity flags, or
you've noun-ed verbs in order to turn an abstract operation into a resource.
E.g. PUT /server-reboot-attempt.

~~~
eterps
_Pure REST is great for toy examples, where every domain entity fits neatly
into a resource and every operation is a CRUD one that can be represented as
an HTTP verb. So there is a million tutorials explaining how to build a REST
API for a blog with BlogPost and Author resources, or an ordering system with
Customer and Order resources._

In my opinion REST is fat more easier to understand for non-CRUD resources.
The whole idea of CRUD makes REST sometimes seem like an HTTP adapter to the
database.

 _However, when you move beyond these simple examples and start trying to
build a REST API for a messy, complex system, you immediately run into
trouble. How do you deal with non-CRUD operations? How do you deal with long
running processes?_

You POST the work to be done to a resource. That resource returns a URL where
you can follow the state of the long running process. An alternative would be
to provide a Webhook that will be called when the long running process has
finished.

 _Or entities in an indeterminate state?_

Same principle, return its actual state on a GET request (polling). Or use a
Webhook (push).

 _How do you aggregate multiple resources into individual request /responses
for performance?_

Use HAL embedding or multipart.

 _How do you de-duplicate identical entities within an aggregated response?_

Use the hypertext caching pattern in your caching layer or proxy. Use the URL
as a unique key.

 _How do you return only particular fields?_

Use HAL embedding, query parameters or a subresource.

 _How do you handle paging and filtering?_

Use link relations and query parameters.

 _How do you handle transactions?_

That's exactly what POST is for.

 _How do you handle authentication and security restrictions?_

Provide a token header over https. Avoid magic URLs based on cookie state
(i.e. even when you are logged in as mike your account details still are at
[https://example.org/user/mike/account](https://example.org/user/mike/account)).
Restrictions are a product of the token and the requested URL.

 _All of these things can be solved, but by the time you 've finished, your
API will be far from easy to understand._

That is true, it won't be easy to understand, but it will be simple,
composable, discoverabe and scalable.

 _It will need a load of accompanying documentation to make it usable_

In my experience the opposite is true, true REST (which includes hypermedia
controls) need less accompanying documentation. It makes resources more
predictable and less dependendent on URLs.

 _All of these things can be solved, but by the time you 've finished, your
API will be far from easy to understand. It will need a load of accompanying
documentation to make it usable, and will have a bunch of weird corners where
you're initiating operations as a side effect of setting entity flags, or
you've noun-ed verbs in order to turn an abstract operation into a resource.
E.g. PUT /server-reboot-attempt._

In stead of making a separate resource for every action it would suffice to
make one that receives actions by POSTing to it. You can respond with a URL
that represents its progress. And it will also save a lot of unnecessary links
or hardcoded URLs.

~~~
sinatra
Any book / link where you think we can get more details about your responses?

~~~
eterps
Most O'Reilly books about REST are really good. If you want to be more
practical I suggest looking for simple ways to introduce hypermedia controls.
In my opinion the HAL JSON standard is the easiest to understand:
[https://www.google.com/search?q=hal+json](https://www.google.com/search?q=hal+json)

------
stilkov
What an incredibly clueless post. I thought we’d left that level of
misunderstanding behind us a few years ago.

There is no such thing as a RESTful URL. Characters in URLs don’t matter.

GET and POST have different semantics. Ignoring the benefits of caching is
just dumb.

The semantics of status codes and verbs are defined pretty clearly. You might
have to read an actual spec.

A paragraph starting with “A core difference between REST and RESTful …”
physically hurts.

I can’t believe I just wasted time actually commenting on this.

------
beders
If you are mapping your RPC-style API into a REST interface, you are doing it
wrong.

REST as an architectural _style_ wants you to think as your API as a
collection of resource representations that can be manipulated through simple
verbs (as the one present in HTTP).

It forces you to think about idem-potency, caching, namespacing, immutability
and robustness.

If your API doesn't have abstractions for long running processes or more
complex business transactions, you don't have a RESTful API and need to adapt
it.

Furthermore, if payload size and minimizing the number of requests is your
most important goal, why are you using HTTP in the first place? It's not the
right solution for you.

~~~
stupidcar
And object orientation wants you to think about your API as a graph of
objects, but going too far down this rabbit hole is how you end up with a mess
of AbstractSingletonProxyFactoryBeans[1]. Yes, it's possible to adapt any
system into a collection of resources, but the transformations necessary to do
so can end up creating more complexity than is gained through only having
resources and verbs. The supposed simplicity of REST can be like the
simplicity of the Brainfuck language. There's only 8 commands! Easy!

And the idea that using HTTP somehow renders questions of performance
irrelevant is bizarre. If Hacker News sent 10MB of uncachable CSS, spread over
100 HTTP requests, with every page load, would that be OK because performance
isn't the most important goal of the web? People use HTTP because it's a
ubiquitous protocol supported by virtually every device and language.
Performance isn't the _most important_ goal, but it's still an important one.

[1] [http://steve-yegge.blogspot.co.uk/2006/03/execution-in-
kingd...](http://steve-yegge.blogspot.co.uk/2006/03/execution-in-kingdom-of-
nouns.html)

------
regularfry
> In other languages API calls don’t return with function pointers to related
> functions.

Let me introduce you to a little something called _objects_.

------
hughes
Completely beside the point of the article, but just seeing a url like
"/customer/33245/order/8769" makes me anxious that the author might give
multiple customers the same order number.

~~~
jrjarrett
So what?

If, in the particular domain, that makes sense, then so what? It may be that
in this context, an "order" is only unique to a customer.

------
xienze
Congratulations, you've discovered RPC.

~~~
ExpiredLink
Strawman

------
omgitstom
It would have been nice if he proposed something innovative moving forward,
but this is a step back to RPC-structured APIs. After reading this though, I
had to check to make sure it wasn't April 1st.

~~~
Nacraile
I think the whole point the article is trying to make is that REST isn't
really a step forward from RPC. It just adds an overly restrictive taxonomy
(i.e. in a complex practical application, you're probably going to run into a
problem that doesn't fit the REST model well), and doesn't actually solve any
real problems.

~~~
lmorchard
REST doesn't add "restrictions". REST describes _constraints_ that - if you
can work within them - provide certain guarantees and benefits and
capabilities. It solves a bunch of real problems. REST wasn't just pulled out
of thin air - it was an attempt to describe how the web itself works at global
scale.

------
treve
How the url is formatted is irrelevant for REST.

~~~
tyrion
Exactly, I don't understand why but it seems to me that a lot of people like
to use the word REST as much as possible without knowing what it actually
means, or without even having read the damn paper :(

~~~
jalfresi
The author CLEARLY has no idea what REST is or even why REST is used. How the
hell did this garbage make it to the front page again?

------
dragonwriter
The criticism they start with is weird. They take this API call:

    
    
      OrderDTO Customer::GetOrder(int customerID, int orderID)
    

And this HTTP call:

    
    
      GET /customer/33245/order/8769
    

And ask:

> If we put the function name between the parameters themselves, then it leads
> to the question, what part of this URL is the endpoint?

But the thing that is between the parameters is "order" not the function name
"GetOrder". If you look at an alternative form in which one might (more
idiomatically, in some languages) see the API call, the relation to the HTTP
call is more clear:

    
    
      Customers[customer_id].Orders[order_id]  # => Order
    

> REST URLs look ‘cleaner’, but are they easier to understand?

Yes.

They go on to say:

> A simpler API, similar to our original function call would have no mixing of
> parameters with the name, and clear definitions of the parameters being
> passed in.

With this example:

    
    
      GET /customer/getOrder?customerID=33245&orderID=8769
    

How is that simpler? Sure, depending on how you've implement the backend, it
may be a more direct reflection of the backend code, but there is a difference
between "leaky abstraction" and "simpler". Also, why is the fact that the
action is "getting" something reflected twice?

> Why not simplify by removing parameters from the URL altogether? Put them in
> the query string, or post body as JSON.

Sure, RPC-over-POST is an alternative (older than REST) style of Web API, and
if that's what floats your boat, do it. OTOH, "removing information from the
URL for aesthetic reasons" may not be the best reason to move a safe operation
from GET, which is defined as safe, to POST, which is neither safe nor
idempotent, particularly if you are using middleware that is aware of HTTP
semantics -- you've just thrown away valuable information.

> Your API can encounter many application specific exceptions while processing
> a request, but why try to pigeon hole your error response into a limited
> number of error codes designed for retrieving hypertext?

Why _not_ choose the best error code of those available in the protocol? In a
traditional programming language, would you just throw the most generic
possible exception? Because that's what the "just use 200 for success and 500
for failure" approach is equivalent to.

> Verb agnostic, HTTP verbs are really only needed to identify where
> parameters will go – for GET it’s in the query string, For POST, in the
> body.

If you are going to use HTTP, why fight against it by throwing out its defined
semantics? Aside from reducing the value you get from existing HTTP-semantics-
aware software, you are just forcing yourself to reinvent the wheel.

> REST is a style, not a standard.

Whether REST is a style or a standard is irrelevant when your post is
advocating abandoning it completely in favor of RPC-over-HTTP with deliberate
disregard for HTTP's defined semantics.

~~~
stcredzero
_OTOH, "removing information from the URL for aesthetic reasons" may not be
the best reason to move a safe operation from GET, which is defined as safe,
to POST, which is neither safe nor idempotent, particularly if you are using
middleware that is aware of HTTP semantics -- you've just thrown away valuable
information._

So a part of the point of and value of GET is to communicate idempotency? We
can know certain parts of the API are idempotent because they are GET?

~~~
ForHackernews
> So a part of the point of and value of GET is to communicate idempotency? We
> can know certain parts of the API are idempotent because they are GET?

Yes:
[http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html](http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html)

~~~
dragonwriter
Pedantically, RFC 2616 is obsolete, and you should point to
[http://tools.ietf.org/html/rfc7231#section-4.1](http://tools.ietf.org/html/rfc7231#section-4.1)

------
aaronem
Microsoft-stack developer doesn't understand how HTTP works. Film at eleven.

~~~
JohnDeHope
I've been feeding my family and paying my mortgage using the Microsoft stack.
God bless it. I also have never understood the REST mojo. I agree with the
original poster. For my money, a url that resolves to a public API end point,
with query string parameters to encode the arguments, is the most
straightforward way to do RPC over HTTP I've used myself. When things get more
complicated, as with an ajax client, then embedding JSON in the request body
has also always worked well for me. Would straight up REST be better? Maybe,
but I don't see it.

~~~
aaronem
Hey, I didn't say anything against the Microsoft stack; I've made a living off
it myself, at times, although mostly at a lower (i.e. VBA) level. But it
doesn't really lend itself to easy understanding of REST.

As far as REST vs. RPC goes, there is a sole essential difference: the
semantics of interaction with a REST resource are defined in RFC 2616, and a
correctly designed and implemented REST resource behaves in accord with what
you find there.

REST itself, meanwhile, being just HTTP, is very simple, and very well suited
to expressing interactions with resources and collections of resources.
Especially in the front-end/full-stack development world, most things can be
expressed, with little or no semantic strain, as resources and collections of
resources, and capable HTTP clients are highly available. (And the convention
of encoding structured data as JSON in request bodies is very strong,
besides.)

Conversely, there are as many RPC-over-HTTP standards as there are
implementations; since doing RPC over HTTP necessarily means mapping whatever
semantics you have in hand to an interface not designed to express them well,
this makes headaches for people who have to develop against them, especially
when writing an application that draws together many disparate APIs in order
to do something interesting at their conjunction.

Whether REST is _better_ than RPC over HTTP, or vice versa, strikes me as a
question for a philosopher. But, in most cases of interacting with a remote
resource over an HTTP transport, REST is certainly more _natural_ , that is,
closer to the native semantics of the transport, which results in thinner glue
layers and more easily understood behavior.

------
BerislavLopac
Wait, was this a serious post or some sort of The Onion-like satire?

------
jawb
REST is good, better than RPC, SOAP... finally people can understand and use
APIs easily and happily. The URL /customer/33245/order/8769 is perfect, looks
like a directory path and reflect the relationship between the entities.
Arguing about the best url, status code and best verb is the irrelevant part
in REST. Why can't people just do whatever it works for the users while
respecting the standards when they can ?!

~~~
lmm
I think you've inadvertently put your figure on the part that really matters.
REST is worse than SOAP or something like Thrift for discoverability, worse
for ease of use, worse for practically every criterion you could think about.
The one thing it does right is being easy to explore with a web browser.

So optimize for that. Make it easy for a developer to look at your API with a
web browser. This means simple URLs. It may mean a limited form of HATEOAS, in
terms of providing links to the next things.

But it absolutely doesn't mean using HTTP status codes to convey important
information. It doesn't mean using content negotiation for API versioning. It
doesn't mean adopting every new HTTP verb, and frankly there's a lot of value
in making every endpoint accessible over GET and POST. Those who insist on
strict REST are missing why it succeeded.

~~~
dragonwriter
> REST is worse than SOAP or something like Thrift for discoverability

How?

> worse for ease of use

How?

> worse for practically every criterion you could think about.

I can think of lots of criteria, but very few on which I can see a compelling
argument for REST being inferior to SOAP except "degree of support from
libraries written to support SOAP".

~~~
lmm
There's no WSDL or .thrift -equivalent for discovery, and no autogenerated
client code which makes use harder. Getting up and running is slower because
you have no way to validate that your messages are well-formed short of
throwing them at the server and seeing what it sends back. What criteria are
you seeing REST as better on?

~~~
dragonwriter
HATEOAS provides both discovery and, when well-known content types are used,
potentially much richer ready-to-use client code than the autogenerated host-
language interfaces provided by SOAP and similar protocols.

~~~
lmm
HATEOAS only lets you discover something by going there, so to speak; it
doesn't give you a complete index like a WSDL.

At the transport level you get much richer and more structured client code
from SOAP. Automated HATEOAS clients are at this point purely theoretical, and
anything you could put a content-type on and send over HATEOAS you could
equally embed in a SOAP response. If the thing you wanted to embed can be
expressed as XML, you can do much better.

~~~
lmorchard
Your browser is an "automated HATEOAS client". You can toss it any old HTML
doc and it knows what to do with things described in the HTML content-type
spec such as links, forms, images, scripts, etc.

~~~
lmm
No, the browser is very much a manual HATEOAS client.

~~~
jalfresi
Incorrect. When you view a html page, the browser fetches the javascript, css
and images in the page automatically.

------
saurabhnanda
I am increasingly getting irritated with REST for our app. It takes too much
thought to figure out the "correct RESTful approach" when building out an API
endpoint. And then again, there are no right answers. And all the JSON
serialization/de-serialization logic, for every single endpoint. Too. Much.
Work.

I'm wondering why Thrift/Proto-buffers aren't popular? Even for browser-based
JS clients. What're the pitfalls?

~~~
lmorchard
Most of the things you describe have nothing to do with REST. That might be
part of your problem :)

------
kolarski
Is it just me or GET /customer/33245/order/8769 is wrong You have unique order
id... then use it GET /order/8769 like that ??

~~~
jrjarrett
What if orderID is NOT unique across the system?

------
kid0m4n
How about this then?

GET /index.php?do=getOrder&customerID=33245&orderID=8769

------
rbelouin
"Does any language force you to prefix a function with 4 verbs?"

Actually, I don't really know. But for sure HTTP isn't forcing you to only use
GET/POST/PUT/DELETE, even if this verbs are usually enough to design your API.
It's quite funny to hear some people (I'm not talking about the author) joking
about the "418 I'm a teapot" response status, which is defined in a HTTP
extension, and then telling you that having only 4 methods to design an API is
too restrictive.

HTTP is extensible, so why misusing it?

------
rcari
Well REST allows for resources to be accessed as they are: resources. Using
POST/GET query parameters implies that the server should do some actual
processing on these to deliver the requested resource. With REST, you can have
the resource be a static file on the server, no processing required.

~~~
creeble
I don't think you need REST to access a static file.

~~~
rcari
Sure, but how convenient it is to just generate the resource once and for all
and dump it in the file system following REST semantics, thus making it
useless to waste CPU cycles computing the resource contents when it's just
there.

------
rondon2
Thank you! I was wondering why I couldn't just use post for a function I'm
writing right now. It helps to have someone else say out loud what I was
thinking.

------
igorescobar
Just another kid with a keyboard and High Speed Internet.

------
LoSboccacc
The answer basically is caches and proxies.

------
giampierod
Why you use GET vs POST are conventions. There are no way to enforce any rules
in web services and conventions help to make the things you are looking at
recognizable. And conventions do change over time. I think we need more HTTP
verbs like START and STOP and I wish POST was NEW. Merge vs. update-all for
PUT is still not well established and now we have PATCH. Such terrible names.
I would love something like REPLACE and MERGE or something more descriptive.

I also think that your customer order example could have been done better.
Something like

Your example: OrderDTO Customer::GetOrder(int customerID, int orderID) But
that's the wrong side of the equation, that's the definition of the function.
If you call the function it would look like this: GetOrder(myCustomerID,
myOrderID)

And an equivalent REST call would look like this with a little clean up. GET
/orders/?id={id}&customer-id={customer-id}

Doesn't look that much different to me. Sure you could have done GET
/orders/{id}/?customer-id={customer-id}, but there is no reason why the above
is wrong from a RESTful perspective. Why would you marshall a whole JSON
payload to do a simple GET? You are not creating a tuple to pass the two
parameters in your full-language function example, what's the reason it is
required for the RESTful call?

As I mentioned above HTTP needs a couple more verbs and aliases for the
existing verbs. You think of situations like:

START /timers STOP /trains

A lot of the time we jam POST and PUT in this situation and they are poor
substitutes for a larger verb vocabulary. I have built a few automation
projects and any actions you do can usually fit into

NEW GET UPDATE (merge) DELETE START STOP OPEN CLOSE

still limited, but pretty good at covering almost all the verbs needed. You
supply the nouns.

NEW /vms START /vms OPEN /remote-desktop/1234 CLOSE /files/folder/path/to/file

Especially with persistent connections in HTTP2 and web sockets and things of
the kind OPEN and CLOSE will likely be need to establish these kinds of
connections. You could probably get away with using START and STOP though,
such as:

START /remote-desktop/?computer=1234

As for HTTP error codes. They need an overhaul. 404 and 403 do the job fine,
but giving the user an idea of whether their JSON was malformed (Syntax) vs.
the data in the payload was invalid is difficult to distinguish with just 400.
But the return payload should describe the error in detail. Not many
conventions there to help.

As for HATEOS, I used to think it was great, but I am meh on it now. It needs
refinement.

