REST,HTTP DELETE和参数


135

向HTTP DELETE请求提供参数是否有非RESTful功能?


我的情况是,我正在建模“确定要删除吗?” 场景。在某些情况下,资源的状态表明所请求的删除可能无效。您可能自己想像一些需要确认删除的情况

我们采用的解决方案是将参数传递给delete请求,以指示可以继续进行删除(“?force_delete = true”)

例如

DELETE http://server/resource/id?force_delete=true

我认为自从以下原因以来,它仍然令人放松:

(a)DELETE的语义未更改-用户仍然可以发送普通的DELETE请求,但此操作可能会失败并显示409,响应主体将说明原因。我说这可能会失败,因为(出于不值得解释的原因)在某些情况下没有理由提示用户。

(b)Roy的论文中没有任何东西表明它与REST的精神背道而驰-为什么会这样,因为HTTP只是REST的一种实现,所以为什么传递HTTP参数会很重要


有人可以指出明确的陈述,说明为什么它不是RESTful的吗?

关于一个相关的问题,如果用户未指定force_delete,那么我正在返回409 Conflict-这是最合适的响应代码吗?


跟进

经过进一步的研究,我认为向DELETE添加参数可能会违反一些原则。

首先是该实现可能违反“统一接口”(请参见Roy论文的 5.1.5节)。

通过添加“ force_delete”,我们在已经定义良好的DELETE方法上添加了一个附加约束。此约束仅对我们有意义。

您也可能会争辩说它违反了“ 5.1.2客户端-服务器”,因为确认对话框确实是UI问题,并非所有客户端都希望确认删除。

建议有人吗?


1
罗伊(Roy)学位论文的网址包含一个导致404的“)”。ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm起作用。
NuclearPeon 2015年

Answers:


78

不,它不是RESTful的。之所以要force_delete在URI中放入动词(),是因为您需要在无法使用PUT / DELETE方法的环境中重载GET / POST方法。从您对DELETE方法的使用来看,情况并非如此。

HTTP错误代码409/Conflict应用于存在冲突的情况,这些冲突会阻止RESTful服务执行该操作,但是用户仍然有可能自己解决冲突。删除前确认(没有真正的冲突可以防止删除)本身就不是冲突,因为没有什么可以阻止API执行所请求的操作。

正如Alex所说的(我不知道是谁对他投了反对票,他是正确的),这应该在UI中处理,因为RESTful服务本身只处理请求,因此应该是无状态的(即,它不能依靠持有有关请求的任何服务器端信息)。

如何在UI中执行此操作的两个示例是:

  • HTML5之前的版本:*向用户显示JS确认对话框,并且仅在用户确认后才发送请求
  • HTML5:*使用具有删除操作的表单,该表单将仅包含“确认”和“取消”按钮(“确认”为提交按钮)

(*)请注意,5之前的HTML版本本身不支持PUT和DELETE HTTP方法,但是大多数现代浏览器可以通过AJAX调用来实现这两种方法。有关跨浏览器支持的详细信息,请参见此线程


更新 (基于其他调查和讨论):

服务要求force_delete=true标志出现的场景违反了Roy Fielding论文中定义的统一接口。另外,按照HTTP RFC的规定,DELETE方法可能在源服务器(客户端)上被覆盖,这意味着这没有在目标服务器(服务)上完成。

因此,一旦服务收到DELETE请求,就应处理该请求而无需任何其他确认(无论该服务是否实际执行了该操作)。


2
您能解释一下哪个REST约束被违反了吗?考虑到URI对客户端来说应该是不透明的,为什么您认为使用HTTP DELETE不能满足客户端的期望,该HTTP DELETE删除一个资源但不能删除另一个资源。我不确定409是返回的最佳状态代码,但是除了有点奇怪的实现之外,我找不到任何破坏的REST约束。
Darrel Miller 2010年

2
@Darrel :(恕我直言)它违反了DELETE方法的统一接口,未按照HTTP标准执行。考虑一个采用标准REST服务的REST客户端-该服务如何让客户端知道需要添加的服务force_delete=true?根据HTTP RFC,可以在源服务器(客户端)上覆盖DELETE方法,这意味着未在目标服务器(服务)上完成此操作。因此,我的理解是,一旦服务收到DELETE请求,它就应该在不需要任何确认的情况下对其进行处理(无论该服务是否实际执行了该操作)。
MicE 2010年

1
@克里斯,第二点:是的,这也是我的理解,即,该状态表明存在真正的冲突,无需确认。我刚刚注意到您在问题中所做的更新,并且我同意-当我自己调查时,我得出了相同的结论(这违反了统一的界面,并且应该在客户端/ UI上进行确认侧)。我还在这里遇到了一个非常有趣的话题
MicE 2010年

2
@MicE在很大程度上,我同意您的看法,这不是处理这种情况的理想方法。我只是对“这不是RESTful”标签有些挑剔。有一阵子在这里把那句话扔了。但是,可以为媒体类型定义规则,即如果您尝试删除资源并且收到错误消息(我说403禁止比409更好),那么客户端应该尝试对相关资源进行删除通过添加“ force_delete = true”。在某种程度上,它有点像授权。执行GET,获取401,添加auth标头,然后再次GET。
Darrel Miller 2010年

2
@Darrel:很好,谢谢。而且我已经看到人们自己抛出了不是RESTful标签。如今,情况可能是服务和Web应用程序之间的障碍变得非常模糊,因此,一组人可以从纯服务的角度看待此问题,而其他人则从混合应用程序/服务的角度看待此问题。那就是我相信有关如何进行确认的真正问题开始起作用的地方。@Chris:更新-谢谢您,先生,我做了一个非常有趣的话题和讨论!
MicE 2010年

35

我认为这是不安的。我认为静态服务不应满足强制用户确认删除的要求。我会在用户界面中处理。

如果这是程序的API,则指定force_delete = true是否有意义?如果有人编写脚本来删除此资源,您是否要强迫他们指定force_delete = true来实际删除资源?


您的回应的第一段是您的意见,我尊重您的看法,但是您没有在文献中指出禁止使用URI这样的内容-它仍然可以标识资源并且正在使用最合适的HTTP动词。回答您的问题;是的,这仍然有意义(我认为)。我希望脚本(也许基于CURL)尊重409响应,并向用户建议如何重新发送请求-全部基于我的响应正文
克里斯·麦考利

比较Web API和程序API的好处。这通常是找出API是否为RESTful的好方法。
劳伦特(Larent)2012年

18

这是一个老问题,但是这里有一些评论...

  1. 在SQL中,DELETE命令接受参数“ CASCADE”,该参数允许您指定还应删除从属对象。这是一个有意义的DELETE参数的示例,但是'man rm'可以提供其他参数。没有参数,如何在REST / HTTP中实现这些情况?
  2. @ Jan,URL的路径部分标识资源似乎是一种公认​​的惯例,而querystring不能(至少不一定)。示例比比皆是:获取相同的资源但格式不同,获取资源的特定字段等。如果我们将查询字符串视为资源标识符的一部分,那么就不可能有“相同资源的不同视图”的概念而无需使用诸如HTTP内容协商之类的非RESTful机制(由于许多原因,这是不希望的)。

感谢您将其添加到对话中,即使它已经持续了数年之久,也算不上什么对话。
silviot 2012年

6

除了亚历克斯的答案:

请注意,http:// server / resource / id?force_delete = true标识的资源与http:// server / resource / id不同。例如,删除/ customers /?status = old还是/ customers /会有很大的不同。

一月


我不同意,我可以自由提供多个URI来标识相同的资源。
克里斯·麦考利

18
是的-每个人都可以随意弄乱:-)
Jan Algermissen

:典型的URI的指示可以在这方面帮助googlewebmastercentral.blogspot.com/2009/02/...
小鼠

@Chris应该只有一个URI返回资源的表示形式。其他URI可以引用相同的概念,但是执行GET应该返回303。只是为了解决明显的反对意见,/ foo.xml和/foo.json是两个不同的资源。
Darrel Miller 2010年

@Darrell-同意,但是格式在这里不是问题。此外,.format是Rails和其他框架(不是REST的一部分)中的约定-您应该在HTTP中使用带有MIME或微格式的内容协商来完全实现这一点。
克里斯·麦考利
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.