问题描述
假设我们有一个"用户"资源,具有唯一的"名称"约束.您如何设计REST API来处理查找或创建(按名称)用例?我看到以下选项:
选项1:多个请求
客户:
POST /user {"name":"bob"}
服务器:
HTTP 409 //or something else
客户:
GET /user?name=bob
服务器:
HTTP 200 //returns existing user
选项2:一个请求,两个响应代码
客户:
POST /user {"name":"bob"}
服务器:
HTTP 200 //returns existing user
(在实际创建用户时,返回HTTP 201而不是)
选项3:请求错误但响应数据包含冲突实体
客户:
POST /user {"name":"bob"}
服务器:
HTTP 409 //as in option1, since no CREATE took place {"id": 1, "name":"bob"} //existing user returned
推荐答案
我相信"正确的"宁静的方式,这将是:
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
我也是重定程后的模式的大粉丝,它将需要使用新创建的用户的URI向客户端发送重定向的服务器.然后,您在案例中的回复将在其正文中拥有200所元件的实体.
这使得1或3次往返服务器. PRG的大优势是保护客户端,即在页面重新加载时重新启动,但您应该阅读更多信息,以确定它是否适合您.
如果这太多了与服务器过分,可以通过读取 https://www.rfc-editor.org/rfc/rfc2616#section-9.5 :
POST方法执行的操作可能不会导致资源 可以通过URI识别.在这种情况下,200(OK)或204 (没有内容)是适当的响应状态,具体取决于是否 或者不是响应包括描述结果的实体.
如果您对远离标准的转向,并且您关注往返,那么选项2是合理的.
其他推荐答案
我正在使用选项2 的版本.创建资源时,我返回201,而 303("查看其他")检索.我选择这样做,因为get_or_create似乎不是共同的休息成语,303是一个略有异常的响应代码.
其他推荐答案
我会选择选项2,原因有两个:
首先,HTTP响应代码,2xx(例如200 nd 201)是指与4xx不同的成功操作.所以在两种情况下,当查找或创建发生时,您可以成功操作.
第二,选项1将服务器的请求数加倍,这可以是重载的性能命中.
问题描述
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 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.
其他推荐答案
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.