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

问题描述:

假设我有两个实体 - 项目团队和员工。每个员工可以是多个团队的一部分,每个团队可以有多个员工作为团队成员。我需要提供REST API来操纵团队,员工和他们之间的关系。在不影响REST中子资源的情况下更新资源的正确HTTP方法

我确定了3个资源 - 团队,员工和成员(团队和员工之间的关联),这是团队的子资源。我选择将会员作为子资源的原因纯粹是基于此资源的生命周期。每当团队被移除时,成员被移除,以及他们在团队本身之外没有意义。

我露出下面的API(相关的):

  • POST /teams创建了名新球队战绩,部门ID等
  • POST /teams/{name}/members创建名称和特定雇员鉴定团队之间的关联,所以输入数据包含员工ID

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

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

貌似PUT是很自然的选择,但PUT的 语义是相当清楚的 - 我 不得不更换整个资源,这 在这种情况下,意味着更换所有 成员子资源也是如此。

我从来没有听说过任何人做过这种关联。如果在我看来PUT /Foo/Foo/bar完全没有说。仅仅因为可以通过分层URI空间访问资源,并不能推断这些资源之间的任何附加关系。

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

+0

这是非常好的一点。我想你是对的,我认为URI是一组资源的严格树形表示。相反,我应该将它们看作只是一种识别方式,其中嵌套意味着指定命名空间。顺便说一句,如果我遵循这个假设,GET的反应将如何看起来像一个“团队”?返回正文中成员的URI是否是好事,或者我应该只返回团队的属性而忽略成员?也许包括像“/ teams/123/members”这样的URI是一种方式吗? – 2011-06-06 02:58:11

+0

@Oleg我会在你的团队代表中包含一个指向'/ teams/123/members'的链接。 – 2011-06-06 12:29:32

+0

谢谢,我需要一个更多的澄清,请在对'/ teams/123'进行PUT时忽略包含'/ teams/123/members'到请求主体的链接是好主意,否则这会混淆客户端? – 2011-06-06 13:15:34

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

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

+0

问题在于使用GET-> modify-> PUT会使服务器上的逻辑显着复杂化。它必须确定哪些关联发生了变化并适当地执行后端操作。我宁愿在方法和主体中传达仅更新团队属性的意图。 – 2011-06-05 23:25:07

+1

另一方面,不把会员作为单独的资源处理可能是一个好主意。因此,如果有人想获得成员名单,它将不得不发出单独的请求,而对于“团队”URI的POST/PUT将始终只处理团队属性 – 2011-06-05 23:27:23

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

另一种看待这个问题的方式是,对资源的每一次更改都是真正“创建新版本”的资源。每创建,更新和删除都添加一个新版本和新属性,并且版本具有其自己的唯一标识符。如果PUT是现有资源的新版本,则旧资源将保留,以便新资源可以继承它。尝试在旧版本上尝试PUT新版本时,如果该资源的较新版本已经存在,将返回重定向而不是成功,所以会有一些GET请求(并不表示它们实际上正在查找旧版本)