在有效负载中包含资源ID或从URI派生


13

在设计API时,我们遇到了一个问题,即PUT有效负载是否应包含要更新的资源的ID。

这是我们目前拥有的:

PUT /users/123 Payload: {name: "Adrian"}

我们的路由代码从URI中提取ID,然后继续进行更新。

API的第一批用户在质疑为什么我们在有效负载中不允许使用ID:

PUT /users/123 Payload: {id: 123, name: "Adrian"}

我们不允许这样做的原因是因为ID在有效负载和URI中重复。

再考虑一下,我们正在将资源耦合到URI。

如果URI没有ID,则需要修改有效负载:

PUT /no/id/here Payload: {name: "Adrian"} < What user???

有什么理由不这样做吗?

Answers:


14

应该将统一资源标识符耦合到资源

使用HTTP实现REST时,可以使用GET检索资源的当前值,并使用PUT设置新值。GET没有有效负载,因此必须由URI标识资源。PUT在逻辑上对相同的URI完成,并且有效负载应与您希望下一个GET返回的内容完全相同。

您可以对不同的URI使用POST,但是这样做的意义不大,因为它不必要地与GET不对称。POST到通用URI仅对创建新资源(POST /users/new,payload:{name: "Adrian"},response {id: 345, name: "Adrian"})有意义,但这不是幂等的,因此应避免 如果您正在努力争取REST¹。相反,您应该通过一次呼叫保留ID,然后使用PUT设置新ID。这是容错的,因为如果第一个请求失败,则ID预留可能最终超时,并且PUT是幂等的。或使用客户端生成的UUID。


¹REST的定义没有提及幂等,因此,如果您具有非幂等操作,我不能真正断言它不是REST。这不会改变以下事实:坚持幂等的请求可以使事情变得更可靠而又不会使其复杂化,因此建议您这样做。


3
据我所知,POST请求不必是幂等的。因此,我认为发布到/users(没有添加“新”)没有问题。
lex82

感谢您的回复。我看到对所有请求具有幂等性是一个很好的功能,但是谁说REST API要求这样做呢?当然,许多自称为RESTful的API都允许非幂等POST请求(尤其是当服务器为新资源生成ID时)。但是,即使您使用了非常严格的REST定义,我也看不到像上面的示例那样使用非幂等POST违反了哪个体系结构约束。
lex82

我当然可以映像违反约束的POST请求。我只是不明白为什么将资源发布到集合中并让服务器决定其ID是否违反REST约束。
lex82


3
POST的整个构想不是幂等的
。...– EralpB

2

再考虑一下,我们正在将资源耦合到URI。

如果URI没有ID,则需要修改有效负载:

PUT / no / id / here有效负载:{name:“ Adrian”} <什么用户???

有什么理由不这样做吗?

这个问题的答案取决于您是否要允许客户端更改ID?

如果客户端可以通过PUT更改ID,则资源的URI将会更改,并且只要资源访问旧的URI,您都应永久提供“ 301移动”。

因此,例如,您从以下资源开始

/users/123

客户端将以下内容放到资源上

{id: 222, name: "Adrian"}

资源已更新,其URI现在是

/users/222

LocationPUT响应中的字段应包含新的URI,如果转到,/users/123则应获得一个301响应,其中Location字段指向新/users/222资源。

在大多数情况下,尽管您实际上并不希望客户端能够更改ID,因为这会很快使您变得混乱。在这种情况下,ID是服务器只能更改的内容,您应该将其放在PUT主体之外,因为客户端无法更新此状态。

如果您将需求放置到同一资源的不同URI中,请说

/users/adian_lync

然后,如果该资源不存在,服务器应创建该资源,并在执行该操作时创建ID


1
我们质疑ID在有效负载中的位置的原因是由于Backbone.js默认情况下将ID传递到PUT请求中。我们可以阻止它的发生,但是现在我想知道为什么这是默认行为。
Adrian Lynch 2014年

1
害怕我对Backbone.js不熟悉。如果ID也包含在URL中,则似乎不必要。也许是部分开发人员的疏忽
Cormac Mulhall 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.