休息uri设计用于更改资源的状态

时间:2013-08-14 13:51:17

标签: json api rest hateoas

我有一个可以在URI /resources/{resource_identifier}上访问的资源,并且它具有我想要访问的'status'属性。我想到了一些选择,这将是“最好的”或“最RESTfull”?

选项一将操作附加到URI并让客户端POST加入这些URI

/resources/{resource_identifier}/void    
/resources/{resource_identifier}/open    
/resources/{resource_identifier}/close

但这看起来很笨拙。


选项二在URI中使用查询参数,并将客户端PATCH添加到这些

/resources/{resource_identifier}?transition=void
/resources/{resource_identifier}?transition=open
/resources/{resource_identifier}?transition=close

选项三使用请求的有效负载并让客户端PUT

/resources/{resource_identifier}

有效负载选项:

{ ..., "status" :"void" }
{ ..., "status" :"open" }
{ ..., "status" :"close" }

或者可能还有别的东西?

6 个答案:

答案 0 :(得分:15)

第一个选项显然不是REST;您在URI中有'actions'并且正在使用POST,这是创建一个新资源,您显然不会尝试这样做。

现在只查看URI格式。选项二越来越好,但这种性质的查询字符串更多用于读取数据。没有什么能阻止你这样做。选项三具有最佳URI格式,它仅引用您要在请求中引用的资源。

如果我们现在考虑请求的方法。在我的书中,这很简单,我假设状态只是该资源的一个字段,因此如果您只进行部分更新,则需要修补资源,因此PATCH是方法使用。在“关闭”的情况下,“状态”是唯一的属性,然后更改状态是完全更改资源,因此PUT是可接受的;但我怀疑情况确实如此。

按照目前的情况,第三个选项的URI与PATCH的使用相结合可能是最好的选择。

PATCH /resources/{resource_identifier}

{ "status" :"close" }

当然,您也可以将其与通过自己的URI公开特定属性的概念结合起来,就好像它们本身就是一种资源一样。坦率地说,我不喜欢这个,因为它感觉很奇怪,一次只适用于一个属性。不过,如果这是你想要使用的,你可以有类似的东西:

PUT /resources/{resource_identifier}/status

close

请记住,没有“正确”的方式来做REST,只是“不坏”的方式。这是一种风格,而不是规则集。

我还建议您考虑能够采用多种格式是一个理想的功能,一般来说。因此,第一种选择往往更容易使用。您可以像示例一样使用JSON,或者将其交换为XML <status>close</ status>,或者简单的键值对status=closed等。

答案 1 :(得分:11)

为什么不将'status'作为资源。你可以管理它。还假设应该已经创建了{status'作为{resource_identifier}资源创建的一部分,并且状态已经存在默认值。

然后业务逻辑需要只是通过其余调用“更新”状态,因此应该使用“PUT”。

<强>更新 将状态移至Put-Body

PUT:    /resources/{resource_identifier}/status/

Body: {void | open | close }

答案 2 :(得分:1)

您的第二个选项看起来更好,因为您正在维护RESTful网址结构,并且不会在其末尾添加RPC样式的方法。

为什么不这样做:

PUT/resources/:id并将transition=void数据与请求一起发送。

它的行为方式与收到POST请求的方式相同,只是从请求正文中获取数据。

答案 3 :(得分:0)

在很多情况下,状态更改具有很多业务逻辑。虽然答案是基于“其他标准”,但我认为在某些情况下,不仅仅是改变状态字段。

例如,如果系统必须取消订单。这不仅仅是更改状态,因为顺序具有许多状态,并且每次更改都代表很多逻辑(通知,验证等)

在使用情况下:

PATCH /order/1
{ "status" :"cancelled" }

我可以向您保证,逻辑将由客户端和服务器分散,将很难维护,并且将没有优雅的代码(尤其是在服务器端,它将验证先前的后续状态) ,如果更改是一致的,则将其与更新职责混合)。

我认为拥有一个cancel方法并完成其工作更为简单。 我认为在许多情况下,这样做更优雅:

PATCH: /order/1/cancel 

//you could use the body with some cancellation data.

以下链接可以为您提供帮助:https://phauer.com/2015/restful-api-design-best-practices/#keep-business-logic-on-the-server-side

答案 4 :(得分:0)

由于PUT,GET和DELETE的标准行为大致映射到CRUD范例,因此有些人认为Resource API仅应用于CRUD用例。但是,这是不正确的评估,因为POST可能会被用来执行无法很好地映射到CRUD的行为。

答案 5 :(得分:0)

在我个人看来,我使用这里普遍同意的两种结构。但是,以下是我画线的方式。

在更新资源属性有副作用的情况下(例如,如果属性值为 XYZ,则发送邮件),我会使其拥有自己的资源(即端点。例如 $product = Product::find($product); ) 这将简化控制器级别的事情。否则,我会使用其父资源 (PUT /resources/:id/status)