Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

find-or-create idiom in REST API design?

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 
like image 878
Nikita Avatar asked Mar 12 '14 02:03

Nikita


People also ask

Which design pattern is used in REST API?

RESTful APIs should take advantage of HTTP methods, or verbs, such as GET, PUT, and POST. RESTful API Design Patterns: API design patterns provide a description or templates to solve specific, recurring API design problems that any software architects and API designers would like to adopt in their API designs.

What are the design principles of REST API?

Here are some of the main design principles of RESTful APIs using HTTP: REST APIs are designed around resources, which are any kind of object, data, or service that can be accessed by the client. REST APIs use a uniform interface, which helps to decouple the client and service implementations.


2 Answers

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.

like image 31
dbn Avatar answered Oct 05 '22 04:10

dbn


I believe the "correct" RESTful way to do this would be :

GET /user?name=bob    200: entity contains user    404: entity does not exist, so         POST /user { "name" : "bob" }            303: GET /user?name=bob                 200: entity contains user 

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://www.rfc-editor.org/rfc/rfc2616#section-9.5:

The action performed by the POST method might not result in a resource that can be identified by a URI. In this case, either 200 (OK) or 204 (No Content) is the appropriate response status, depending on whether or not the response includes an entity that describes the result.

If you're okay with veering away from the standard, and you're concerned about round-trips, then Option 2 is reasonable.

like image 186
Eric Stein Avatar answered Oct 05 '22 04:10

Eric Stein