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

Web services 在不影响REST中的子资源的情况下更新资源的正确HTTP方法,web-services,api,rest,Web Services,Api,Rest,假设我有两个实体——项目团队和员工。每个员工可以是多个团队的一部分,每个团队可以有多个员工作为团队成员。我需要提供RESTAPI来操纵团队、员工以及他们之间的关系 我已经确定了3种资源-团队、员工和成员(团队和员工之间的关联),这是团队的子资源。我选择将成员作为子资源的原因纯粹是基于此资源的生命周期。无论何时团队被移除,成员都会被移除,因为他们在团队之外没有任何意义 我公开了以下API(相关API): POST/teams创建带有姓名、部门ID等的新团队记录 POST/teams/{name}

假设我有两个实体——项目团队和员工。每个员工可以是多个团队的一部分,每个团队可以有多个员工作为团队成员。我需要提供RESTAPI来操纵团队、员工以及他们之间的关系

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

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

  • POST/teams
    创建带有姓名、部门ID等的新团队记录
  • POST/teams/{name}/members
    在按姓名标识的团队和特定员工之间创建关联,因此输入数据包含员工ID
我还需要提供API来在一个请求中更新部门ID和团队的其他属性。看起来PUT是自然选择,但PUT的语义非常清楚-我必须替换整个资源,在本例中,这意味着替换所有成员以及子资源


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

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


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

我认为您在回答自己的问题
PUT
建议创建资源,更新时使用
POST

另一种看待这一点的方式是,对资源的每一次更改实际上都是“创建一个新版本”的资源。每次创建、更新和删除都会添加一个具有新属性的新版本,该版本有自己的唯一标识符。当您
放置现有资源的新版本时,旧资源将保留,以便新资源可以从中继承。当资源的较新版本已经存在时,尝试将新版本置于较旧版本上会返回重定向而不是成功,一些
获取
请求(那些不表示他们实际上正在寻找旧版本的请求)也会返回重定向

看起来看跌期权是自然选择,但是 PUT的语义非常清楚-I 必须替换整个资源,这 在这种情况下,意味着更换所有 成员还包括子资源

我以前从来没有听说过有人这样做。在我看来,如果你把/Foo
放在
/Foo/bar
上,那绝对没有什么意义。仅仅因为可以通过层次URI空间访问资源,并不能推断这些资源之间的任何其他关系


我听说有人在做相反的事情,你把/Foo/bar放入
/Foo
,如果服务器知道这会影响
/Foo
的状态,你可以包含一个指向
/Foo
的内容位置头,允许智能缓存失效
/Foo
。但是,需要使用内容位置来显式地创建两个资源之间的关系。

问题在于,使用GET->modify->PUT将使服务器上的逻辑变得非常复杂。它必须确定哪些关联已更改,并适当地执行后端操作。我宁愿在方法和主体中传达只更新团队属性的意图。另一方面,不将成员视为单独的资源可能是个好主意。所以,如果有人想要获得成员列表,就必须发出单独的请求,而“团队”URI上的POST/PUT将始终只操纵团队属性。这一点非常好。我认为您说得对,我认为URI是一组资源的严格树表示。相反,我应该把它们看作是一种标识方法,其中嵌套意味着名称空间的规范。顺便说一句,如果我同意这个假设,一个“团队”会得到什么样的回应?返回正文中成员的URI是一件好事,还是我应该只返回团队的属性而忽略成员?也许包括像“/teams/123/members”这样的URI是一种方法?@Oleg我会在您的团队表示中包括一个指向
/teams/123/members
的链接。谢谢,我需要更多的说明,请,在执行PUT to
/teams/123
时,在请求正文中省略包含指向
/teams/123/members
的链接是否是一个好主意,或者这会混淆客户端?可以从PUT请求正文中安全地省略表示中不受客户端控制的@Oleg元素,例如超媒体链接。