HTTP PUT和DELETE的幂等性

dan*_*wig 8 api rest http asp.net-web-api

所以HTTP规范说HTTP PUT和DELETE应该是幂等的.这意味着,对具有相同正文的同一URL的多个PUT请求不应导致服务器上的其他副作用.多个HTTP DELETE也是如此,如果将2个或更多DELETE请求发送到同一个URL,则第二个(或第三个等)请求不应返回指示资源已被删除的错误.

但是,在处理完DELETE之后,PUT对URI的请求呢?它应该返回404吗?

例如,请考虑以下顺序执行以下请求:

  • POST/api/items - 创建item资源,返回HTTP 201和URI/api/items/6
  • PUT/api/items/6 - 更新与item#6 相关的数据
  • PUT/api/items/6 - 只要请求体与先前的PUT相同,就没有副作用
  • DELETE/api/items/6 - 删除item#6并返回HTTP 202
  • DELETE/api/items/6 - 没有副作用,并且还返回HTTP 202
  • GET/api/items/6 - 这将返回404
  • PUT/api/items/6 - 这里应该发生什么?404?409?别的什么?

那么,如果PUT与获取和返回404一致,或者像@CodeCaster建议的那样,409会更合适吗?

Cod*_*ter 11

RFC 2616,第9.6节,PUT:

POST和PUT请求之间的根本区别体现在Request-URI的不同含义上.POST请求中的URI标识将处理所包含实体的资源.该资源可能是数据接受过程,某些其他协议的网关或接受注释的单独实体.相反,PUT请求中的URI标识请求附带的实体 - 用户代理知道URI的用途,并且服务器不得尝试将请求应用于其他资源.

和:

如果无法使用Request-URI创建或修改资源,则应该给出适当的错误响应,以反映问题的性质.

所以定义'适当'是看400系列,表明存在客户端错误.首先,我将消除不相关的:

  • 400错误请求:由于语法格式错误,服务器无法理解请求.
  • 401 Unauthorized:该请求需要用户身份验证.
  • 402需要付款:此代码留作将来使用.
  • 406 Not Acceptable:请求标识的资源根据请求中发送的接受标头不可接受.
  • 407需要代理身份验证:此代码[...]表示客户端必须首先使用代理进行身份验证.
  • 408请求超时:客户端在服务器准备等待的时间内未生成请求.
  • 411所需长度:服务器拒绝接受没有定义Content-Length的请求.

那么,我们可以使用哪些?

403禁止

服务器理解请求,但拒绝履行请求.授权无效,请求不应重复.

这个描述实际上非常适合,尽管它通常用在与权限相关的上下文中(如:你可能不会......).

404未找到

服务器未找到与Request-URI匹配的任何内容.没有说明该病症是暂时的还是永久性的.如果服务器通过一些内部可配置的机制知道旧资源永久不可用且没有转发地址,则应该使用410(Gone)状态代码.当服务器不希望确切地说明请求被拒绝的原因,或者没有其他响应适用时,通常会使用此状态代码.

这也是,尤其是最后一行.

405方法不允许

请求行中指定的方法不允许由Request-URI标识的资源.响应必须包含一个Allow标头,其中包含所请求资源的有效方法列表.

我们没有可以响应的有效方法,因为我们现在不希望在此资源上执行任何方法,因此我们无法返回405.

409冲突

冲突最有可能发生在响应PUT请求时.例如,如果正在使用版本控制并且包含PUT的实体更改为与早期(第三方)请求所产生的资源冲突的资源,则服务器可能会使用409响应来指示它无法完成请求.在这种情况下,响应实体可能包含由响应Content-Type定义的格式的两个版本之间的差异列表.

但是假设URI上已经存在资源(如何与任何东西发生冲突?).

410已经走了

请求的资源在服务器上不再可用,并且不知道转发地址.预计这种情况将被视为永久性的.具有链接编辑功能的客户端应该在用户批准后删除对Request-URI的引用.如果服务器不知道或无法确定条件是否是永久性的,则应该使用状态代码404(未找到).

这也是有道理的.


我已经编辑了这篇文章几次,当它声称"使用410或404"时它被接受,但现在我认为403也可能适用,因为RFC没有声明403必须与权限相关(但它似乎是通过流行的Web服务器实现的.我想我已经淘汰了所有其他400个代码,但随意评论(在你downvote之前).