2011-12-23 130 views
44

支持数据服务的取消删除或延迟/批处理删除是相当常见的要求。我想知道的是如何以REST方式实现这一点。我在几个不同的选择之间撕裂(其中没有一个对我来说似乎非常有吸引力)。我相信,在这些不同的选项中,通常需要一个API,它将返回标记为特定资源类型已删除的所有资源。REST风格取消删除

这里是我想过和他们的一些优点/缺点的一些选项:

为删除

选项来标记资源:

  • 使用HTTP DELETE来标记资源为已删除。
  • 使用HTTP PUT/POST更新已删除的标志。这并不正确,因为它将本质上是从HTTP DELETE方法中删除的内容映射到其他HTTP方法中。

选项时GET-ING资源标记为删除:

  • 返回HTTP状态404资源被标记为删除。清除&透明,但我们如何区分真正删除的资源与刚刚标记为已删除的资源之间的区别。
  • 返回HTTP状态410.提供方式来说明不同之处,但从技术上说410“预计被认为是永久性的。具有链接编辑功能的客户应该在用户批准后删除对Request-URI的引用。这里的“预计”和“应该”可能有足够的摆动空间。不确定410在客户中的支持/理解程度如何。
  • 返回HTTP状态200并且包括标志字段指示资源被删除。这看起来很奇怪,因为首先删除它的想法是因为你真的希望它不出现。这推动了将已删除资源过滤到客户端的责任。为响应,其中包括该删除资源

选项:

  • 忽略makred为已删除的资源。清洁&简单。但是如果你真的想知道被删除的资源呢。
  • 将它们与指示它们被删除的字段一起包括在内。这推动了将已删除资源过滤到客户端的责任。如果您只想通过活动或已删除的资源进行分页,分页会变得非常棘手。

选项时更新资源标记为删除:

  • 使用HTTP状态404资源没有了吧?但是,您如何能够区分标记为已删除的资源和实际删除的资源。 404响应中的HTTP主体可能会在此消除歧义,但客户端仍然会解析/解释您的身体以消除歧义。也许响应标题可能有帮助吗?哪一个?自定义标题?
  • 使用HTTP状态409,提供有关资源如何首先被取消删除的消息。

选项取消删除资源标记为删除:对资源的更新操作

  • 使用HTTP PUT/POST,并再次将其标记为活动。只有当您没有为资源的GET操作返回HTTP 404时,它才会起作用,因为它不会因为PUT/POST而导致资源为“未找到”(404)。
  • 使用HTTP PUT/POST进行资源的创建操作。这里的问题是哪些数据优先?在创建操作中发送的数据?或者正在取消删除的数据?将其过滤出任何其他将会返回它的查询。然后,如果资源标识符指向标记为已删除的资源,则将创建资源的HTTP PUT/POST视为取消删除。
  • 单独的REST路径专用于标记为删除的取消删除资源。

这绝不是一个详尽的清单。我只想列举一些在我脑海中弹跳的选项。

我知道如何做到这一点的答案是,像往常一样,“这取决于”。我很好奇的是你会用什么资格/要求做出决定?你怎么看到这个实现或自己实现它?

+2

这是迄今为止我在StackOverflow上见过的最充分准备和深思熟虑的问题之一。有一个upvote。 – 2014-05-16 19:23:46

回答

4

我认为解决这个问题的最RESTful方法是使用HTTP PUT来标记要删除的资源(并取消删除),然后使用HTTP DELETE永久删除资源。要获得标记为删除的资源列表,我将使用HTTP GET请求中的参数,例如。 ?state=markedForDeletion。 如果您请求标记为不带参数删除的资源,我认为您应该返回“404 Not Found”状态。

8

去经书:RFC 2616-9.7

The DELETE method requests that the origin server delete the resource 
    identified by the Request-URI. This method MAY be overridden by human 
    intervention (or other means) on the origin server. The client cannot 
    be guaranteed that the operation has been carried out, even if the 
    status code returned from the origin server indicates that the action 
    has been completed successfully. However, the server SHOULD NOT 
    indicate success unless, at the time the response is given, if it intends 
    to delete the resource or move it to an inaccessible location. 

当你删除一个资源服务器应该标志着它的侧删除该资源。它并不需要删除资源,它不能保证操作已经执行。即使如此,服务器不应该说它没有被删除。

A successful response SHOULD be 200 (OK) if the response includes an entity 
    describing the status, 202 (Accepted) if the action has not yet been enacted, 
    or 204 (No Content) if the action has been enacted but the response does not 
    include an entity. 

如果操作被延迟,则发送一个202和一个描述操作结果的实体。 (想象一下代表服务器延迟删除资源的可轮询“任务”;理论上它可以永远保留在该状态下。)只需要阻止客户端以原始形式再次检索它。使用410作为响应代码,当“任务”完成或服务器以其他方式删除资源时,返回404。这不是你正在寻找的删除,而是一个添加状态转换,它改变资源状态,但保持可访问性?在这种情况下,使用PUT/PATCH来更新资源并完成。

+3

关于在删除资源后如何可以RESTfully取消删除资源的任何建议? – Caleb 2011-12-24 02:33:18

+0

在这种情况下,您实际上并没有删除资源,只是限制了对资源的访问。理论上讲,不会有任何东西阻止你,删除资源,从该任务添加状态转换到“重新创建”它。从语义纯度角度来看,我不太喜欢这种方法,但至少比绕过HTTP语义更清晰。 – jmkeyes 2011-12-24 02:36:38

+0

好的答案,但是自从2616被替换为7231之后,它对DELETE语义有不同的描述,并且我还有其他一些东西需要添加,我已经发布了一个新的。 – 2017-09-27 21:51:36

1

短版

你不能REST风格撤消删除使用它的原始URI的任何方法的资源 - 这是不合逻辑的,因为试图在已被删除返回值应该是404或410的资源的任何操作。(强调)虽然这是没有明确的规范说明,强烈的DELETE方法1的定义暗示:

实际上,这种方法类似于UNIX rm命令:它 表达删除操作对源 服务器的URI映射,而不是期望先前关联的 信息被删除。

换句话说,当您删除资源时,服务器不再将该URI映射到该数据。所以你不能PUT或POST等等。(请记住,资源被定义为URI和一些基础数据之间的映射)。

一些解决方案

,因为它是明确指出,基础数据并不一定删除,不排除作出 URI的映射为DELETE实现的一部分的服务器,从而有效地使一个备份副本,可以稍后恢复。

您可以拥有一个包含所有已删除项目的“/ deleted /”集合 - 但您将如何实际执行取消删除操作?也许最简单的RESTful方法是让客户端使用GET检索项目,然后将其发布到所需的URL。

如果您需要能够将删除的项目恢复到原来的位置,该怎么办?如果您使用支持它的媒体类型,则可以将原始URI包含在来自/ deleted/collection的GET响应中。客户端然后可以使用它来发布。这样的反应可能是这样的JSON:然后

{ 
    "original-url":"/some/place/this/was/deleted/from", 
    "body":<base64 encoded body> 
} 

客户端可以张贴该机构到URI来执行撤消删除。另外,如果你的资源定义允许移动的概念(通过更新一个“位置”属性或类似的东西),那么你可以做一个部分更新并避免整个对象的往返行程。或者,做大多数人做的事,并实施类似RPC的操作,告诉服务器移动资源! UnrESTful,是的,但在大多数情况下它可能会正常工作。

如何决定这些事情

关于你如何决定这些事情的问题是:你必须考虑一下在你的应用程序的情况下删除手段,为什么你想要它。在很多应用程序中,没有任何东西会被删除,“删除”实际上意味着“从所有进一步的查询/列表中排除此项目,除非我明确地取消删除它”。所以,它实际上只是一个元数据或移动操作。在这种情况下,为什么要使用HTTP DELETE?一个原因可能是,如果你想要一个2层删除 - 一个可撤销的软或临时版本,以及一个难以/永久的版本,那么......不是。

缺席任何具体的应用场景,我会倾向于执行他们是这样的:

我不希望任何看到这个资源更长的时间,为了我的方便POST部分更新标记资源作为“临时删除”

我不希望任何人能够达到的任何此资源不再因为它是尴尬/罪证/成本我钱的/ etcHTTP DELETE

下一个需要考虑的问题是:永久删除只应该永久地取消映射URI,以便任何人都不能再链接到它,或者是否有必要清除底层数据?显然,如果你保存了数据,那么管理员甚至可以恢复“永久”删除的资源(但不是通过任何RESTful接口)。这样做的缺点是,如果数据的所有者真的希望清除数据,那么管理员必须在REST界面之外执行此操作。

0

删除的项目也是资源,对不对?就这样吧。然后我们就可以访问这个资源这种方式(比如,我们已经删除的用户):

PATCH deleted_users/{id} // I personally use this one 

或者这样说:

PATCH deleted/users/{id} 

或有些人可能认为这是更舒适的方式:

PATCH deleted/{id}?type=users