我在设计 REST API 时对选择方法有疑问。
我们的 REST API 将由 SPA 应用程序(在相关情况下在 React 中创建)使用,以添加/更新组织模型,如下所示 -
Class Organization{
List<Student> students;
List<Teacher> teachers;
}
我们计划提供 Post 和 Patch 方法来与我们的 API 交互。
对于补丁,我们是否应该保留一个可以接受请求主体的单一端点,如下所示,SPA 可以发送其中一个实体进行更新。
方法 1 -
补丁
/api/organization
{
"students":[],
"teachers":[]
}
或者我们是否应该提供两个单独的端点来更新特定实体?
方法 2 -
/api/organization/students/{id}
/api/organization/teachers/{id}
(请注意,在真实场景中大约有 10 个这样的实体)
SPA 团队赞成方法 1 保持单一端点,这使他们可以灵活地将任何实体发送到单个补丁端点,而不必跟踪每个实体的不同端点。
另一方面,API 团队支持每个实体的补丁端点方法 2,这样他们就可以根据他们收到的每个实体的补丁调用在后端生成事件,而不必通过请求主体来查看发生了什么英寸
是否有适用于上述场景的 REST 标准来选择一种方法而不是另一种方法?
我绝对会推荐#2。
使用方法 #1,如果其中一个补丁失败,您将很难对错误做出反应。
补丁是针对单个资源的,而不是集合。
如何处理缓存等?规范明确了 ETags 和单个资源,服务器应该如何处理并发变化?
我看不出将客户端的工作卸载到服务器有什么帮助,它让一切变得更加复杂。
对于补丁,我们是否应该保留一个可以接受请求主体的单一端点,如下所示,SPA 可以发送其中一个实体进行更新。
这取决于:你用什么来
GET
?你有一个、两个或三个资源吗?
如果您通过
GET /api/organization
支持阅读,并且在您返回的表示中嵌入了学生和教师的所有详细信息,那么您通常应该想要修补组织资源。
另一方面,如果
GET /api/organization
返回链接到其他地方的数据的表示(例如 /api/organization/students/1),那么您通常应该定位具有您想要更改的表示的链接资源。
记住,您正在实现一个外观,使您的服务看起来像一个 HTTP 感知文档存储。因此,您的端点应该以与文档存储相同的方式理解 PATCH 请求:补丁旨在应用于由请求的目标 uri 标识的文档。
换种方式表达:PATCH 真的不关心资源是否捕获有关数据库中单个实体或多个实体的信息。这都是关于资源(即:网页)和对该网页的表示进行远程创作更改。
这几乎就是 REST 的“统一接口”约束的全部要点——所有资源都以相同的方式理解请求消息,无论它们是如何在外观背后实现的。
PATCH 的一个限制可能会影响您对资源模型的选择:
服务器必须以原子方式应用整个更改集,并且从不提供(例如,在此操作期间响应 GET)部分修改的表示。 -- RFC 5789
因此,如果同时修补教师和学生需要分布式事务,那么您可能不想要建议他们可以原子地一起更改的资源模型。
使用的启发式非常简单:你将如何在网页上排列这些信息?
如果所有内容都嵌入到单个 HTML 文档中,那么您当然会修补该文档。另一方面,如果主文档链接到其他文档,那么您将修补主文档以更改链接,并修补链接目标以更改从那里返回的表示。