我正在设计一个管理收藏夹的RESTful API。每个喜欢的资源都可以包含两个被视为收藏夹一部分的项目的详细信息。
HTTP POST /favorites
{ "item1" : "ball",
"item1-ID" : "1",
"item2" : "bat",
"item2-ID" : "2"
}
请原谅基本的JSON有效载荷。然而,重点是POST的语义
上面的POST方法会创建一个新的收藏资源(包含一个球(ID 1)和一个球棒(ID 2))
我的问题是关于两次发送相同POST请求时的预期行为。第一个请求将创建一个收藏夹(如预期的那样)。发送第二个请求时会发生什么?
1)用409
发出错误信号2)用201
表示成功1)不是幂等的(如POST所示),而2)使POST具有幂等性。
哪种方法正确?
答案 0 :(得分:1)
对我而言,正如你所描绘的那样,它应该创造一个新的喜爱。但对于几乎任何应用来说,这都很奇怪。如果:
如您所见,这一切都取决于您的申请。
也许你可以从我刚刚写的这篇文章中得到一些想法:A look into various REST APIs。不要错过底部的摘要。
答案 1 :(得分:0)
你正在以错误的方式思考这个问题。如果POST
创建新资源,则资源应具有标识该资源的URL(例如,http://.../favorite/1
)。当具有相同有效负载的第二个POST
发生时,是否创建了新资源?如果是这样,那么您有两个具有唯一URL的独立资源。如果您的应用程序未创建新资源,则第二个POST
将返回与第一个相同的URL。
修改强>
RFC7231的POST
部分并不禁止以幂等方式实施它。它确实提供了一些指导:
POST
创建新资源,那么它应该发送包含标识所创建资源的Location标头的201(已创建)响应POST
的结果等同于现有资源,则服务器可以通过返回具有相应Location标题的303(请参阅其他)来将UA重定向到现有资源 POST
不是必需来更改资源的状态。但是,GET
和HEAD
必需是幂等的。我不知道在服务器上更改状态所需的任何方法。
就个人而言,我实现了资源创建POST
方法,作为实践,将303重定向返回到资源的规范URL。我不知道用于资源创建和重用响应的RFC区分状态代码。这种方法的好处是它不需要在POST
响应中包含创建的资源,而GET
规范URL将在任何可能存在的中间缓存中缓存响应。它还允许实现不检索响应并使用规范URL(来自Location标题)的智能客户端。
在你的情况下,我认为我会采用303方法,前提是收藏夹有自己的URL;如果没有,201会很奇怪。如果有很好的理由来区分响应中的创建和重用情况,那么创建新资源时的201和重新使用时的303是合适的。除非您的应用程序要求您拒绝创建已存在的资源,否则我不会返回409。
答案 2 :(得分:0)
发送第二个请求时会发生什么?
这完全取决于您的实施。假如您的控制器中有一些逻辑检查数据库中是否存在ID 1和ID 2,则更新该值,否则创建新记录。 整个事情不依赖于POST请求。
AND FYI成功的HTTP响应代码是200而不是201.
您当前的方法不正确,问题不是JAVA问题
答案 3 :(得分:0)
通常,它取决于您,您希望如何设计底层系统。在大多数情况下,POST会创建一个新资源(是的,当您使用POST而不创建任何新内容时会有实例。例如,您有一个用例,您希望在其中搜索很长的参数列表并获取GET可能不是这样!这是完全可以接受的,并不违反REST原则。)
评论您的具体案例,
发送第二个请求时会发生什么?
您应该向自己提出以下问题。
是否有重复请求(具有相同有效负载/标题/时间戳等的请求)对您的系统有“不同”请求?如果是 - 通常将其视为不重复。我假设请求所针对的下一个系统也将其理解为 new 请求,否则它们可能会失败并标记错误。例如,MySQL可能会抛出Duplicate Primary Key错误(请参阅:Error Code: 1062. Duplicate entry 'PRIMARY')
如果(1)的答案为否 - 此请求的重复出现是否是客户的预期行为? (例如,如果间歇性地获取网络,您倾向于从移动设备获得重复请求。)如果是 - 返回200 OK。注意这里的幂等性。
如果(2)的答案为否 - 抛出409与客户端可以处理并做出相应反应的自定义错误代码冲突。我还会调查客户端在抛出重复请求时的不良行为,并在可行的情况下修复它。