8

If I am using a UUID to identify the entity as part of my URI of my REST endpoint:

/entities/<uuid>/

and that UUID is generated by the client when creating new entities, is there a best practice as far as using PUT vs POST? In other words the UUID is generated by the client as opposed to by the server.

If I were to use PUT, is it expected that the message payload contain the UUID as well? In this case the both the message as well as the URI identifying the entity would contain the UUID.

For spec, see: the REST RFC

Alex Rothberg
  • 10,243
  • 13
  • 60
  • 120
  • 1
    You are confusing "REST" with "HTTP". There is no "REST RFC". There is a "HTTP RFC", but nowadays it's not RFC 2616 anymore. – Julian Reschke Oct 15 '14 at 07:11

3 Answers3

4

Since you (the client) already know the UUID, I would say PUT is the best practice, and you don't need to include UUID in the payload. Admittedly, PUT vs POST is somewhat controversial and reading and re-reading the RFC doesn't totally clear it up for me. But I think the preceding is orthodoxy.

See PUT vs POST in REST for a nice discussion.

Community
  • 1
  • 1
Eric
  • 1,691
  • 16
  • 24
  • Is it true that "you don't need to include UUID in the payload"? That seems to contradict what @nikita said about needing to include the UUID since it is part of the representation of the resource. – Alex Rothberg Oct 15 '14 at 04:52
  • The name of the resource does not need to be part of the representation. – Julian Reschke Oct 15 '14 at 07:10
1

Understand the difference between PUT and POST.

PUT is meant to replace resource (http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.6) pointed to by the URI with a new one. And it is idempotent i.e. how many times you invoke it with same payload, the result is same; it will make the same resource available through the URI.

So, if the resource is not there already a new one is created. Even in this case the result is same i.e. it will make the same resource available through the URI.

POST is meant create a sub-resource (http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5) to the resource pointed to by the URI. If the resource is a list then it will add an item to it. If it is item then it should add something to the item, an attribute may be.

So, ideally if the item pointed to by the URI is not available then it should be an error condition. May be a “404”. POST is all about adding to an existing resource.

Coming to your question, it is best to use POST with “/entities/“ as URI as per the description above. You should not use a non-existent resource UUID in the URI with POST method. If you are using PUT then use “/entities/”.

POST /entities/ HTTP/1.1
Content-Type: application/json
{
   UUID: <UUID>..
   OtherStuff: ...
}

PUT /entities/<UUID> HTTP/1.1
Content-Type: application/json
{
   UUID: <UUID>..
   OtherStuff: ...
}

Response should be same

HTTP/1.1 201 Created
Location: http://www.examples.com/entities/<uuid>/

although PUT is idempotent but if the PUT method is used again then it should use 200 or 204 in response.

Your second question: ideally the full resource detail should be in the PUT payload instead of just URI.

Julian Reschke
  • 40,156
  • 8
  • 95
  • 98
Pankaj Jangid
  • 524
  • 3
  • 18
  • You presented two ways of creating a new resource: `POST` without the UUID and `PUT` with the UUID. Which of these is preferred in this case where the UUID is generated client side? – Alex Rothberg Oct 15 '14 at 15:48
  • 1
    I prefer POST without UUID to create a new resource. Because I have kept it this way that a URI should always point to an existing resource. This way I don't get confused. Also to make PUT really idempotent it should always return with same response if the payload is same. But if you create new resource with PUT and also update with PUT it will return two different types of responses. In create it is 201 and otherwise it is 200. This breaks the semantics. – Pankaj Jangid Oct 16 '14 at 05:08
-1

The main difference between POST and PUT:

POST is used to append new entities. POST is not idempotent. That means if you send POST request ten times you'll create ten different entities. Usually you should get 201(Created) response code to POST request coupled with Location header pointing to URL of newly created resource. In your case I suggest to POST to URL sthm like

POST /entities/ HTTP/1.1
Content-Type: application/json
{
   UUID: <UUID>..
   OtherStuff: ...
}

Response:

HTTP/1.1 201 Created
Location: http://www.myREST/entities/<uuid>/

PUT request is used to modify existing state. PUT is idempotent. Usually you'll get 200(OK) response code.

You need to contain UUID in PUT/POST payload. UUID is part of representation of your resource. PUT and POST both transfer representation to REST server in order to change/append resource state.

BTW you should't use URI term in REST. URI is sthm that may not has representation, though URL always has representation.

nikita
  • 2,737
  • 2
  • 20
  • 26
  • If I have a uniqueness constraint on UUID does that change anything (This is essentially a must since I rely on UUID be a canonical lookup for the entity)? So if I try to POST the same UUID multiple times, only the first is successfully 201. Should I be concerned / care that if I were to use PUT to create I am specifying the data in that the URL and the payload both contain the (hopefully) same UUID? – Alex Rothberg Oct 15 '14 at 04:50
  • 1. In your case(SINCE you are generating UUID on the client) subsequent POST's should reply 409(Conflict). Anyway you should include UUID in POST since server should point you to resource that it created for client. It creates it using UUID that client provided.2. It's best practice. It's the way client and server communicate each other - by transferring representations back and forth. – nikita Oct 15 '14 at 05:21
  • Do you mean you should include the UUID in `PUT`? presumably you have to include it in the POST since the URL does not include the UUID. – Alex Rothberg Oct 15 '14 at 05:40
  • You should not count on URL in that case. REST does not state the format of URL. It could be absolutely random. Consider PUT as SQL UPDATE statement. When you do UPDATE you always add WHERE ID='' clause, right? – nikita Oct 15 '14 at 05:48
  • 1
    Okay. So given that I do include the UUID in each request (PUT or POST), if I am generating the UUID at the client, which should I use for the creating: PUT or POST? – Alex Rothberg Oct 15 '14 at 05:53
  • POST to INSERT, PUT to UPDATE – nikita Oct 15 '14 at 06:00
  • POST does not necessarily create new resources (in this example, repeating with the same UUID in the payload might just update the subresource). Also your statements about URL vs URI are very confusing. – Julian Reschke Oct 15 '14 at 07:13
  • @JulianReschke Canonically, POST is to append/create. As for URI vs URL difference - https://en.wikipedia.org/wiki/Uniform_resource_identifier. URI could also be URN which doesn't has any representation. That is where idea of Linked Data came from to RDF. – nikita Oct 15 '14 at 07:32
  • nikita: I recommend you look at the relevant RFCs (here 3986 and 7231), not outdated ones or Wikipedia. POST definitively can update if you want it to. And a resource identified by a URN definitively can have a representation, it's just harder to obtain. – Julian Reschke Oct 15 '14 at 07:42
  • @JulianReschke Fine. Show me how to get representation of URN:ISBN:978-1-449-35806-8. As for POST to UPDATE - I've seen systems where GET was used to UPDATE, which doesn't make them better. – nikita Oct 15 '14 at 07:47
  • Nikita: I didn't say *all* have a representation. As to GET vs POST: your point being? Again: what's relevant is what the specs say, not hearsay or Wikipedia articles. – Julian Reschke Oct 15 '14 at 09:42
  • @JulianReschke So.. you shouldn't use URI term in REST, since it may not have representation(p.1.1.3 in RFC 3986). As for POST your point taken. RFC 7231 does not say that POST is used for INSERT(first statement), HOWEVER all that is written in RFC about POST is about insert and that was my answer. – nikita Oct 15 '14 at 10:03
  • I prefer to stick to the definition of REST; see http://roy.gbiv.com/pubs/dissertation/evaluation.htm#sec_6_2 – Julian Reschke Oct 15 '14 at 10:12