我实施了一个重命名公司的API,如下所示:
PUT /companies/A
{
"name": "B"
}
将返回HTTP 301
,Location
标题指向公司的新URI:/companies/B
。
如果有If-Match
标题,我怎样才能使此操作具有幂等性?
没有If-Match
标题:如果用户尝试重命名不存在的公司,我希望服务器返回HTTP 404
,但我不能这样做,因为那时合法重命名操作不是幂等的(它们第一次返回301
,后续调用时返回404
。这是有问题的,因为我希望客户能够区分失败的重命名(公司不存在)与已经发生的重命名。
使用If-Match
标头:如果公司的ETag
取决于公司名称,则后续重命名操作将失败,因为前提条件不再成立。同样,这使得操作似乎失败了,实际上它已经发生了。
答案 0 :(得分:6)
好的,这已经两年了,但是我会回答它,以防其他人像我一样偶然发现它。
简短的回答是,从HTTP的角度来看,重命名(移动)资源不幂等,您应该使用POST
代替PUT
。< / p>
答案很长:PUT
是一个“创建或替换”操作,由RFC 2616定义如下(强调我的):
PUT
方法请求在提供的Request-URI 下存储所包含的实体。
RFC 7231(此时此问题仅作为草案存在),更明确地说明了这一点:
PUT
方法请求目标资源的状态 用表示定义的状态创建或替换 包含在请求消息有效负载中。成功的PUT
表示会建议后续的GET
目标资源将导致等效表示 已通过200
(OK
)回复发送。
由于成功重命名会导致资源在不同的位置可用,因此PUT
不适用。
PS。您可以通过在请求正文中包含公司的某种唯一标识符(无论其名称或其他属性)来使用PUT
,这样您就可以检测以前的重命名并发出适当的重定向。然而,我认为这违反了协议,POST
会更合适。
答案 1 :(得分:2)
PUT操作成功,应该返回200或201.对同一资源的后续请求应返回301,其中相应的响应主体指示新资源的URI。
404应仅适用于真正无法找到的资源,即那些不存在且从未拥有的资源。如protocol中所述,幂等并不意味着该调用始终返回相同的内容。这意味着没有副作用。此外,幂等在错误条件下不适用,除了2xx之外的任何东西(如301)都是。
我真的很佩服通过规范来做到正确的承诺,但就像所有事情一样,它需要解释。
答案 2 :(得分:0)
我不认为3xx在这里有意义。 PUT操作成功,因此应返回2xx。 301意味着资源不是请求者认为的资源。
一般来说,当他们真正想要MOVE时,我一直对不使用MOVE的人感到好笑: - )