如何编写 delete REST API 接受一长串要删除的项目?

How to write delete REST API that accepts a long list of items to delete?

我正在编写 RESTful API 并且正在习惯使用 HTTP 动词进行不同操作的推荐协议。

但是,我不确定这些协议如何处理您删除可能很长的项目列表的情况。

似乎与 GET 一样,DELETE 动词没有正文,因此限制为 URL 的长度。那么,您如何支持接受任意长的待删除项目列表?

自上而下....

HTTP is our standard for self-descriptive messages, which is subject to the uniform interface constraint。这反过来意味着网络上的每个人都以相同的方式理解 HTTP 请求。

换句话说

DELETE /api/users/5b45eda8-067c-42c1-ae1b-e0f82ad736d6

同义
DELETE /www/home.html

在这两种情况下,我们都要求服务器对其 资源模型 进行更改。

因为每个人都以相同的方式理解这些请求,我们可以创建通用组件(例如:缓存)来理解 transfer of documents over a network domain 中消息的含义,因此可以做一些智能的事情(比如使以前缓存的响应无效) ).

即使通用组件对资源的语义一无所知,对隐藏在资源背后的底层领域模型一无所知,我们也可以做到这一点。

DELETE,在HTTP中,总是指定一个单一的目标URI; “批量删除”不是此处的选项。

(我还没有找到任何 registered HTTP methods 来描述对通用组件的批量删除。可能其中一种 WebDAV 方法可以表达这些语义,但 WebDAV 标准还有很多其他的行李 - 我不会尝试将这些方法重新用于“正常”API。)

因此,如果您尝试删除 API 中的三个资源,那么您将需要三个请求才能完成——就像您尝试删除网站上的三个页面一样网站。


也就是说,如果使用单个 HTTP 请求删除您网站上的一堆 资源 比让通用组件了解正在发生的事情更重要:您有使用 POST

的选项

POST serves many useful purposes in HTTP, including the general purpose of “this action isn’t worth standardizing.” -- Fielding, 2009

通用组件会理解目标 URI 标识的资源正在以某种方式发生变化,但它不会理解负载中发生的事情。

理论上,您可以标准化表示“我们正在删除所有这些资源”的有效载荷,然后可以实施通用组件以识别该标准。在实践中,祝你好运。


现在,如果您想要的是批量删除 域模型 中的实体,您有一些可用的选项。

在网络上,我们通常会使用类似表单的东西——可能每个实体都有一个复选框。您 select 要删除的实体,提交表单,HTTP 请求处理程序解析消息,然后将信息转发到您的域模型。

您可以使用远程创作惯用法实现类似的效果 - 这是一个资源,其表示形式是实体列表。您将删除了实体的该文档的副本放入服务器,然后在服务器上对域模型进行更改以匹配。

这是一种非常声明性的方法:“更改域模型,使资源的表示形式如下所示”。

这类似于您使用 HTTP 修复网页中的拼写错误的方式:在请求正文中发送一个带有新 HTML(包括拼写更正)的 PUT 请求。

PATCH 的想法非常相似:我们描述对资源表示的更改,服务器将该信息传递给域模型。这里的不同之处在于,我们没有发送整个表示,而是发送了一个描述更正的补丁文档。

如果您想要命令式方法 - 只需使用 POST

POST /Bob
Content-Type: text/plain

Bob,
Please delete domain entities 1, 2, 5, 7

通用组件不会理解您试图修改目标资源的方式,但它们至少会知道这么多。


当有大量资源的表示依赖于相同的资源时,事情就会变得混乱。这些标准并没有为我们提供太多的方式来宣布“这里是所有已更改的资源”。

缓存失效是两大难题之一。 HTTP 有一些适用于简单情况的功能,但当事情变得更复杂时,权衡就变得必要了。