用于在不影响REST中的子资源的情况下更新资源的正确HTTP方法

时间:2011-06-05 22:53:55

标签: web-services api rest

我们假设我有两个实体 - 项目团队和员工。每个员工都可以成为多个团队的一员,每个团队可以拥有多名员工作为团队成员。我需要提供REST API来操纵团队,员工和他们之间的关系。

我已经确定了3个资源 - 团队,员工和成员(团队和员工之间的关联),这是团队的子资源。我选择将成员作为子资源的原因完全基于此资源的生命周期。每当团队被移除时,成员都会被删除,而且他们在团队之外没有任何意义。

我公开了以下API(相关的API):

  • POST /teams创建包含姓名,部门ID等的新团队记录。
  • POST /teams/{name}/members在名称和特定员工识别的团队之间创建关联,因此输入数据包含员工ID

我还需要提供API以在一个请求中更新团队ID和团队的其他属性。看起来像PUT是自然的选择,但PUT的语义非常清楚 - 我必须替换整个资源,在这种情况下,也意味着替换所有成员子资源。

当我只想在保留成员关联的同时更新团队的属性时,我应该使用什么方法(或方法)?请记住,我也希望此请求是幂等的。

3 个答案:

答案 0 :(得分:5)

  

看起来PUT是很自然的选择   PUT的语义非常清楚 - 我   必须替换整个资源,其中   在这种情况下意味着替换所有   成员子资源。

我以前从未听过有人做过这种联想。如果我认为PUT /Foo完全没有提及/Foo/bar。仅仅因为可以通过分层URI空间访问资源,不会推断这些资源之间的任何其他关系。

我听说有人在做PUT /Foo/bar的相反情况,如果服务器知道这会影响/Foo的状态,则可以包含指向{{的Content-Location标头1}}允许智能缓存使/Foo无效。但是,需要Content-Location来明确创建两个资源之间的关系。

答案 1 :(得分:2)

理想情况下,您应该使用PATCH方法,但不确定哪个实现使用它。如果没有,你应该直接GET - >本地修改 - > PUT循环。

此外,根据您的设计,您可能会认为子资源不属于资源本身。例如,团队资源的内容可能包含指向资源成员列表的链接,例如“/team/{name}/members”,但不包含整个列表作为包含元素。

答案 2 :(得分:-2)

我觉得你在回答自己的问题。 PUT建议资源的创建POST用于更新。

另一种看待这种情况的方法是,对资源的每次更改都实际上是“创建资源的新版本”。每次创建,更新和删除都会添加具有新属性的新版本,版本具有自己的唯一标识符。当您PUT现有资源的新版本时,旧资源仍然存在,以便新资源可以从中继承。当已存在该资源的较新版本时,尝试PUT旧版本上的新版本将返回重定向而不是成功,因此某些GET请求(不指示该请求)他们实际上在寻找旧版本)