
Using HTTP Verbs correctly in your REST Web API - micheltriana
http://micheltriana.com/2013/09/30/http-verbs-in-a-rest-web-api/
======
ripberge
How do you guys deal with "actions" in your API's that are not CRUD? Something
like reserving an airline seat where you just want to pass in an id of a seat
and a user id. I guess that's what PATCH would be for? I was unaware of this
verb until today.

What I'm struggling with is that REST does not seem to fit with how we use the
web today. These HTTP verbs were designed for a document centric era of the
web, not for the complex _processes_ we're modeling today. I'm not really
seeing REST being easier to design or consume than RPC style web api's--isn't
that the whole point?

I mean if you were designing an API to be consumed internally in Ruby/JAVA/C#
etc, would you design it like REST? I wouldn't. Why have we all become
convinced we need to do this for a web api?

~~~
hayksaakian
POST to /reservations

~~~
ripberge
So I'd have to POST an object that represents a process? It seems like you end
up cluttering your code with objects to represent every process? Which in OO
programming would just be a method call...

~~~
phamilton
The point is to avoid implicit state. By treating the change in state as a
first class citizen you can be explicit about the change. In my experience,
managing state is very difficult in large applications. Most of the bugs I've
dealt with have been the result of our design not being explicit enough.

------
joshfraser
Is there a good reason why so many API's avoid using PUT and DELETE? Take the
Twitter API for example, they use POST /lists/destroy instead of DELETE. They
are smart guys and clearly know how to design a RESTful API. What's their
rationale?

~~~
wereHamster
You can't PUT or DELETE from a html <form>.

~~~
joshfraser
I knew there was a simple explanation that I was forgetting.

~~~
est
because some stupid waf only allow POST/GET methods on port 80.

------
dxhdr
What's so bad about implementing RPC via HTTP using Json or similar? Sticking
to just REST "verbs" seems ridiculous to me... unless you're making yet
another CRUD app, then I suppose it works out fine.

~~~
pragueexpat
Agree. For me, best practice is to use JSON-RPC for our client to server
communication and expose a REST interface for 3rd party CRUD operations.

------
jamesbritt
This chart, for POST, has it returning the new user.

Strictly speaking, why would a POST return something other than status info
and a URL for the created resource (if successful)?

The spec says:

 _If a resource has been created on the origin server, the response SHOULD be
201 (Created) and contain an entity which describes the status of the request
and refers to the new resource, and a Location header (see section 14.30)._

Is it assumed that the client will automatically follow that Location header
and GET this resource? That would make some sense (perhaps most of the time)
but that's different from having the POST request itself return the resource
directly which is what's suggested by this chart.

~~~
wereHamster
Saves you one roundtrip.

~~~
jamesbritt
This is true, and is an argument for pragmatism over strict adherence to the
spec.

But if we take that route at what point do we start telling people they're
doing it wrong or that they're API isn't _really_ RESTful?

I'm inclined to think the answer is "never" and just encourage people to
create APIs that are appropriate for the actual circumstances.

There are generally practical reasons to be RESTy, but "a foolish consistency"
and all that comes into play as well.

------
elchief
Can't bulk delete though. Should a super-user be able to bulk delete?

The status codes are:

 _/ api/users:_

GET 200 OK

POST 201 Created (or 205 thanks lgierth)

PUT 204 No Content

DELETE 405 Method Not Allowed

PATCH 204 No Content

 _/ api/users/123:_

GET 200 OK

POST 405 Method Not Allowed

PUT 200 OK

DELETE 204 No Content

PATCH 200 OK

return 404 if resource not found, or 410 Gone if you know it once existed

return 400 (or 422) and list of errors on invalid input.

return 401 if need to login.

return 403 if logged in but not allowed to do something.

return 409 Conflict on currency control issue.

~~~
aaronem
The PATCH verb seems underspecified and warty to me. Why not instead accept,
on a PUT request, a Range header [1] whose byte-range-spec defines the range
to be replaced in the document? Along with an entity consisting of the partial
content to use in the replacement, this seems to provide everything the PATCH
verb does, plus a complete absence of the ambiguity involved in "[description
of changes]".

Say maybe thus:

    
    
      GET /users/123 HTTP/1.1
      Host: www.example.com
      Connection: keep-alive
      
    
      HTTP/1.1 200 OK
      Content-Type: text/json
      Content-Length: 41
    
      {"name":"Joe","email":"joe@example.com"}
    
      
      PUT /users/123 HTTP/1.1
      Host: www.example.com
      Connection: keep-alive
      Range: 24-27
    
      j.random.hacker
      
    
      HTTP/1.1 200 OK
      Content-Type: text/json; charset=ISO-8859-1
      Content-Length: 53
    
      {"name":"Joe","email":"j.random.hacker@example.com"}
    

[1]
[http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14...](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35)

~~~
myhf
Byte-ranges aren't idempotent like complete documents and key/value pairs are.
You would need a vector-clock reference as well as the byte-range to let the
server resolve ambiguity in your byte-range.

~~~
aaronem
See my response to wereHamster [1]; in short, you're right, which is why RFC
2616 specifies entity tags and the If-Match request header.

[1]
[https://news.ycombinator.com/item?id=6494134](https://news.ycombinator.com/item?id=6494134)

------
joshguthrie
If you really want to use HTTP Verbs correctly, follow this:
[http://i.stack.imgur.com/whhD1.png](http://i.stack.imgur.com/whhD1.png)

~~~
dragonwriter
That doesn't diagram using HTTP verbs correctly, it diagrams using HTTP
response codes.

And it's also _wrong_ viewed in light of RFC 2616 (HTTP/1.1), at least with
regard to PUT (particularly, it doesn't address the case where the spec
indicates the server must use a 301 for a PUT.)

------
rpedela
Unfortunately URLs are not encrypted when using HTTPS. There are cases when a
GET request will have potentially sensitive information such as a filter with
an email address or unique identifier in it. In this case it is best to use
one of the other verbs that can have body like POST and put the filter in the
body. I like the standard definition of a REST API but sometimes it does not
match the real world.

~~~
batbomb
That isn't true. URLs are encrypted, otherwise logging in wouldn't work.

~~~
aioprisan
There is no such thing as encrypted URLs. Encrypted parameter values, maybe..
I believe you're referring to SSL, which is the underlying transport protocol.

~~~
batbomb
I was referring to the fact that the parent said URLS weren't encrypted over
HTTPS, which is not true.

