1

I have a REST API where:

GET or POST /foo/{foo_id}/bar?a=1,b=2,c=3

and

GET /bar/{bar_id}

both yield

200 { bar_id: <GUID>, foo_id: <foo_id>, a: 1, b: 2, c:3 }

When no matching bar is found for the first call, bar will be generated and persisted. The operation is idempotent, but it is potentially not read-only. Should the first call be a GET or a POST? I am leaning towards both, because I can't find a convincing argument for one over the other in everything I have read on the subject.

  • I assume that you have default values for a, b, and c? Without them, you wouldn't be able to use a GET as a creation mechanism. If you want to follow the "standard" precisely, GET can only get a resource that already exists. – Robert Harvey Jul 30 '16 at 17:49
  • No defaults, but the parameters are required. – Blake Mitchell Jul 30 '16 at 19:57
  • Ah, so GET /bar/{bar_id} when no resource exists still yields an error. – Robert Harvey Jul 30 '16 at 21:25
4

GET should never create a resource. Not one that is visible to the user. It's a read-only operation.

The standard for both POST and PUT is to also return a 201 Created code, instead of 200 OK, when a resource has been persisted. That is to completely distinguish whether a resource has been saved or simply retrieved.

You should ditch GET completely. If the first operation will always create a bar resource and will return a 409 Conflict when a resource with the same identifier already exists, it's optimal if you used POST.

However, if you want to create a bar resource when a new one is passed or simply use an already existing one, you could even use PUT instead of POST. PUT is usually used for both creation and update of a resource, ie. it creates it when none-matching is found or updates it. But remember, PUT should be only used when you can update an entire resource during one request. For partial updates the PATCH method is much more suitable.

  • Fun fact: we only use POST in our API. But it's not strictly a CRUD mechanism, so. – Robert Harvey Jul 30 '16 at 18:31
  • @RobertHarvey I used to do quite the same, but recently found the PUT and PATCH methods quite fitting for several situations. Though POST is probably the most general one and can be used virtually for any resource creation. – Andy Jul 30 '16 at 19:19
  • I'm in, GET really is not appropriate. I'm starting to think the first API should be POST /bar?foo_id={foo_id}&a={a}&b={b}&c={c} and use 200/201 to discern if the bar was pre-existing or created. – Blake Mitchell Jul 30 '16 at 20:06
  • There is no problem with GET creating a resource. But the client should not use GET to create a resource. – Cormac Mulhall Aug 3 '16 at 10:34
2

Should the first call be a GET or a POST?

It should be a GET.

The key reason is that the client, if I'm following correctly, does not know it is creating a resource nor is setting out to create a resource.

The client wants the current state of the resource from the server. It is not aware this might mean creating a resource and it does not care one jolt that this is the first time anyone has attempted to get this resource before, nor that the server has to create the resource on its end (what ever that means in the context of the server).

The client just wants the current state of that resource.

REST has nothing to do with CRUD operations on the server side. In fact the point of REST is that those details should be hidden from the client. The client doesn't care at all what the server has to do to manage to give the client a representation of the resource. If the server has to run a big SQL query in a transaction to create this resource, client doesn't care.

The thing to remember here is the direction of control. The client is saying to the server give me your representation of resource foobar. That is what GET is. how the server does that is up to the server.

If you used POST or PUT that is the client saying "Here is my representation of foobar, update yourself"

But in your scenario the client isn't responsible for the initial creation of foobar, the server is. The client just wants the server's representation and should be unaware of any side effects from that operation.

  • This was exactly my line of thought when I first created the API, but the rest of my team agree with @david-packer in that the write operation makes it a POST. I guess this is the grey area of not having a formal definition of REST. This page supports that GET is the correct method as it is both safe and idempotent: restcookbook.com/HTTP%20Methods/idempotency – Blake Mitchell Aug 3 '16 at 16:54
  • 1
    Well luckily there is a formal definition of REST, it is Roy Fielding's thesis where he defined the term and the idea behind it. The problem is that in software development often the Big Idea gets lost as developers learn about ideas through a series of school playground Chinese Whispers. I would strongly recommend going to the source, the thesis is kinda heavy going but it grounds all other discussion of REST in terms of what the big concept Fielding is describing. – Cormac Mulhall Aug 3 '16 at 17:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.