删除多个项目的 REST-ful 方式是什么?
我的用例是我有一个主干集合,其中我需要能够一次删除多个项目。选项似乎是:
为每条记录发送一个 DELETE 请求(如果可能有几十个项目,这似乎是个坏主意);发送一个 DELETE,其中要删除的 ID 在 URL 中串在一起(即“/records/1;2;3”);以非 REST 方式,发送一个自定义 JSON 对象,其中包含标记为删除的 ID。
所有选项都不太理想。
这似乎是 REST 约定的灰色区域。
是一个可行的 RESTful 选择,但显然有您所描述的限制。不要这样做。中间人会将其解释为“删除 /records/1;2;3 处的(单个)资源”——因此,对此的 2xx 响应可能会导致他们清除 /records/1;2;3 的缓存;不清除 /records/1、/records/2 或 /records/3;代理 /records/1;2;3 的 410 响应,或其他从您的角度来看没有意义的事情。这种选择是最好的,并且可以以 REST 方式完成。如果您正在创建 API 并且希望允许对资源进行大规模更改,则可以使用 REST 来完成,但具体如何做对许多人来说并不是很明显。一种方法是创建一个“更改请求”资源(例如,通过将诸如 records=[1,2,3] 之类的主体发布到 /delete-requests)并轮询创建的资源(由响应的 Location 标头指定)以查看您的请求是否已被接受、拒绝、正在进行或已完成。这对于长时间运行的操作很有用。另一种方法是向列表资源 /records 发送 PATCH 请求,其主体包含资源列表和要对这些资源执行的操作(以您希望支持的任何格式)。这对于请求的响应代码可以指示操作结果的快速操作很有用。
一切都可以在保持 REST 约束的情况下实现,通常答案是将“问题”变成资源,并给它一个 URL。因此,批量操作,例如在此处删除,或将多个项目发布到列表,或对大量资源进行相同的编辑,都可以通过创建“批量操作”列表并将新操作发布到它来处理。
不要忘记,REST 并不是解决任何问题的唯一方法。 “REST”只是一种架构风格,您不必必须遵守它(但如果不遵守,您将失去互联网的某些好处)。我建议您查看此 HTTP API architectures 列表并选择适合您的列表。如果您选择其他架构,请让自己意识到您会失去什么,并根据您的用例做出明智的决定。
Patterns for handling batch operations in REST web services? 上的这个问题有一些不好的答案,有太多的赞成票,但也应该阅读。
如果 GET /records?filteringCriteria
返回符合条件的所有记录的数组,则 DELETE /records?filteringCriteria
可以删除所有此类记录。
在这种情况下,您的问题的答案是 DELETE /records?id=1&id=2&id=3
。
GET /records?id=1&id=2&id=3
not 是否表示“获取 ID 为 1、2 和3”,意思是“获取URL路径/records?id=1&id=2&id=3的单一资源”,可能是萝卜的图片,中文包含数字“42”的纯文本文档,或者可能不存在。
/records?id=1
和 /records?id=2
的两个连续请求,并且它们的响应由某些中介(例如您的浏览器或 ISP)缓存。如果 Internet 知道您的应用程序的含义,那么可以通过简单地合并(以某种方式)它已经拥有的两个结果,而无需询问原始服务器,就可以通过缓存返回对 /records?id=1&id=2
的请求。但这是不可能的。 /records?id=1&id=2
可能无效(每个请求只允许使用 1 个 ID)或可能返回完全不同的东西(萝卜)。
id[]=1&id[]=2
还是 id=1&id=2
来表示值数组,该查询字符串都代表了这一点。而且我认为这是非常普遍的&让查询字符串表示过滤器的好习惯。此外,如果您允许删除和更新,请不要缓存 GET
请求。如果您这样做,客户端将保持陈旧状态。
我认为 Mozilla Storage Service SyncStorage API v1.5 是使用 REST 删除多条记录的好方法。
删除整个集合。
DELETE https://<endpoint-url>/storage/<collection>
使用单个请求从集合中删除多个 BSO。
DELETE https://<endpoint-url>/storage/<collection>?ids=<ids>
ids:从集合中删除其 id 在提供的逗号分隔列表中的 BSO。最多可以提供 100 个 ID。
删除给定位置的 BSO。
DELETE https://<endpoint-url>/storage/<collection>/<id>
http://moz-services-docs.readthedocs.io/en/latest/storage/apis-1.5.html#api-instructions
这似乎是 REST 约定的灰色区域。
是的,到目前为止,我只遇到过一个提到批量操作(例如批量删除)的 REST API 设计指南:google api design guide。
本指南mentions创建可以使用冒号通过资源关联的“自定义”方法,例如 https://service.name/v1/some/resource/name:customVerb
,它还明确提到批处理操作作为用例:
自定义方法可以与资源、集合或服务相关联。它可以接受任意请求并返回任意响应,并且还支持流式请求和响应。 [...] 自定义方法应该使用 HTTP POST 动词,因为它具有最灵活的语义 [...] 对于性能关键方法,提供自定义批处理方法以减少每个请求的开销可能很有用。
所以你可以根据谷歌的api指南做以下事情:
POST /api/path/to/your/collection:batchDelete
...删除您的收藏资源中的一堆项目。
If the HTTP verb used for the custom method does not accept an HTTP request body (GET, DELETE), the HTTP configuration of such method must not use the body clause at all,
。但是 GET accounts.locations.batchGet
api 是带有 body 的 GET 方法。这很奇怪。 developers.google.com/my-business/reference/rest/v4/…
POST
使用的http方法,只有自定义方法被命名为batchGet
。我猜谷歌这样做是为了(a)坚持他们的规则,即所有自定义方法都必须是 POST
(请参阅我的答案)和(b)让人们更容易在正文中放置“过滤器”,所以你这样做不必像查询字符串那样对过滤器进行转义或编码。当然,缺点是这不再是真正可缓存的了……
我允许对集合进行大规模替换,例如 PUT ~/people/123/shoes
,其中 body 是整个集合表示。
这适用于客户想要查看项目并删除一些项目并添加一些其他项目然后更新服务器的小型项目集合。他们可以 PUT 一个空集合来删除所有集合。
这意味着即使 PUT 删除了 GET ~/people/123/shoes/9
,它仍会保留在缓存中,但这只是一个缓存问题,如果其他人删除了该鞋,这将是一个问题。
我的数据/系统 API 始终使用 ETags 而不是到期时间,因此每个请求都会命中服务器,并且我需要正确的版本/并发标头来改变数据。对于只读和视图/报告对齐的 API,我确实使用过期时间来减少对来源的点击,例如排行榜可以持续 10 分钟。
对于更大的集合,例如 ~/people
,我往往不需要多次删除,用例往往不会自然出现,因此单个 DELETE 可以正常工作。
将来,根据构建 REST API 和遇到相同问题和要求(如审计)的经验,我倾向于仅使用 GET 和 POST 动词并围绕事件进行设计,例如 POST 地址更改事件,尽管我怀疑会有自己的一系列问题:)
我还允许前端开发人员构建他们自己的 API,这些 API 使用更严格的后端 API,因为他们不喜欢严格的“Fielding zealot”REST API 设计通常有实际、有效的客户端原因,并且为了提高生产力和缓存分层的原因。
您可以发布已删除的资源:)。 URL 为 POST /deleted-records
,正文为 {"ids": [1, 2, 3]}
DELETE
请求,则被请求者和服务器之间的任何东西都会认为指定 URL 处的单个资源正在被删除。查询字符串是这些设备的 URL 的不透明部分,因此无论您如何指定 API,它们都不了解这些知识,因此不会有不同的行为。DELETE
请求传递请求正文。不要这样做。如果你这样做,我会吃掉你的孩子。名义名义名义。