find-or-create idiom in REST API design?

橙三吉。 提交于 2019-12-03 22:27:01

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://tools.ietf.org/html/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.

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 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.

I believe a GET request which either:

  • returns an existing record; or
  • creates a new record and returns it

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:

Naturally, it is not possible to ensure that the server does not generate side-effects as a result of performing a GET request; in fact, some dynamic resources consider that a feature. The important distinction here is that the user did not request the side-effects, so therefore cannot be held accountable for them.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!