say we have a 'user' resource with unique constraint on 'name'. how would you design a REST API to handle a find-or-create (by name) use case? I see the following options:
option 1: multiple requests
client:
POST /user
{"name":"bob"}
server:
HTTP 409 //or something else
client:
GET /user?name=bob
server:
HTTP 200 //returns existing user
option 2: one request, two response codes
client:
POST /user
{"name":"bob"}
server:
HTTP 200 //returns existing user
(in case user is actually created, return HTTP 201 instead)
option 3: request errs but response data contains conflicting entity
client:
POST /user
{"name":"bob"}
server:
HTTP 409 //as in option1, since no CREATE took place
{"id": 1, "name":"bob"} //existing user returned
I believe a GET request which either:
is the most efficient approach as discussed in my answer here: Creating user record / profile for first time sign in
It is irrelevant that the server needs to create the record before returning it in the response as explained by @Cormac Mulhall and @Blake Mitchell in REST Lazy Reference Create GET or POST?
This is also explained in Section 9.1.1 of the HTTP specification:
I am using a version of option 2. I return 201 when the resource is created, and 303 ("see other") when it is merely retrieved. I chose to do this, in part, because get_or_create doesn't seem to be a common REST idiom, and 303 is a slightly unusual response code.
I believe the "correct" RESTful way to do this would be :
I'm also a big fan of the Post-Redirect-Get pattern, which would entail the server sending a redirect to the client with the uri of the newly created user. Your response in the POST case would then have the entity in its body with a status code of 200.
This does mean either 1 or 3 round-trips to the server. The big advantage of PRG is protecting the client from rePOSTing when a page reload occurs, but you should read more about it to decide if it's right for you.
If this is too much back-and-forth with the server, you can do option 2. This is not strictly RESTful by my reading of https://tools.ietf.org/html/rfc2616#section-9.5:
If you're okay with veering away from the standard, and you're concerned about round-trips, then Option 2 is reasonable.
I would go with Option 2 for two reasons:
First, HTTP response code, 2xx (e.g. 200 nd 201) refers to a successful operation unlike 4xx. So in both cases when find or create occurs you have a successful operation.
Second, Option 1 doubles the number of requests to the server which can be a performance hit for heavy load.