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

Sur*_*esh 15 api rest json hateoas

我有一个可以在URI处访问的资源,/resources/{resource_identifier}它有一个我想要访问的"status"属性.我想到了一些选择,这将是"最好的"或"最RESTfull"?

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

/resources/{resource_identifier}/void    
/resources/{resource_identifier}/open    
/resources/{resource_identifier}/close
Run Code Online (Sandbox Code Playgroud)

这看起来很笨拙.


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

/resources/{resource_identifier}?transition=void
/resources/{resource_identifier}?transition=open
/resources/{resource_identifier}?transition=close
Run Code Online (Sandbox Code Playgroud)

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

/resources/{resource_identifier}
Run Code Online (Sandbox Code Playgroud)

负载选项:

{ ..., "status" :"void" }
{ ..., "status" :"open" }
{ ..., "status" :"close" }
Run Code Online (Sandbox Code Playgroud)

或者可能还有别的东西?

the*_*man 18

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

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

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

就目前而言,第三个选项的URI与使用相结合PATCH可能是最好的选择.

PATCH /resources/{resource_identifier}

{ "status" :"close" }
Run Code Online (Sandbox Code Playgroud)

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

PUT /resources/{resource_identifier}/status

close
Run Code Online (Sandbox Code Playgroud)

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

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

  • GitHub REST API 为我们提供了一些与此讨论相关的示例。看看他们如何[处理锁定问题](https://docs.github.com/en/free-pro-team@latest/rest/reference/issues#lock-an-issue)例如:他们`PUT .. ./issues/{issue_number}/lock` 和 `DELETE .../issues/{issue_number}/lock`。有趣的是,这类似于现实生活中实际加锁(PUT)和删除(DELETE)某物。 (4认同)

Min*_*han 12

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

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

更新 移动状态到Put-Body

PUT:    /resources/{resource_identifier}/status/

Body: {void | open | close }
Run Code Online (Sandbox Code Playgroud)

  • 我认为PUTing/status/resource是有道理的.虽然你不会把实际状态:无效,打开,关闭在PUT的主体而不是作为URI的一部分? (2认同)

Bar*_*rto 5

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

例如,如果系统必须取消订单。这并不是简单地改变一个状态,因为订单有很多状态,每个改变都代表着很多逻辑(通知、验证等)。

在使用的情况下:

PATCH /order/1
{ "status" :"cancelled" }
Run Code Online (Sandbox Code Playgroud)

我可以向你保证,逻辑会被客户端和服务器分散,很难维护,而且不会有优雅的代码(特别是在服务器端,它会验证先前、后续的状态,如果变更是一致的,并且会与更新责任混合在一起)。

我认为有一个取消方法并完成它的工作更简单。我认为在很多情况下这样做更优雅:

PATCH: /order/1/cancel 

//you could use the body with some cancellation data.
Run Code Online (Sandbox Code Playgroud)

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


Kri*_*ian 1

您的第二个选项看起来更好,因为您维护 RESTful url 结构,而不是在其末尾附加 RPC 样式的方法。

为什么不这样做:

PUT并随请求/resources/:id发送数据。transition=void

它的行为方式与您接收 POST 请求时的行为相同,只需从请求正文中获取数据即可。