关于属性更新的Restful业务逻辑

关于属性更新的Restful业务逻辑,rest,api-design,Rest,Api Design,我正在构建一个RESTAPI,并试图尽可能保持它的RESTful,但有些事情对我来说仍然不太清楚。我看到了很多关于类似问题的话题,但都集中在更新数据的“简单”问题上,我的问题更多的是围绕这个问题的业务逻辑 我的主要问题是由模型的部分更新触发的业务逻辑。我在网上看到很多关于补丁方法、创建新的子资源或添加操作的不同意见,但与保持URI简单和结构化的REST方法相比,这似乎常常适得其反 我有一些记录需要处理(拒绝、验证、部分验证等),每次更改都会触发额外的操作 如果被拒绝,应发送一封包含拒绝原因的电

我正在构建一个RESTAPI,并试图尽可能保持它的RESTful,但有些事情对我来说仍然不太清楚。我看到了很多关于类似问题的话题,但都集中在更新数据的“简单”问题上,我的问题更多的是围绕这个问题的业务逻辑

我的主要问题是由模型的部分更新触发的业务逻辑。我在网上看到很多关于补丁方法、创建新的子资源或添加操作的不同意见,但与保持URI简单和结构化的REST方法相比,这似乎常常适得其反

我有一些记录需要处理(拒绝、验证、部分验证等),每次更改都会触发额外的操作

  • 如果被拒绝,应发送一封包含拒绝原因的电子邮件
  • 如果部分验证,则发送用于完成缺失数据的链接
  • 如果已验证,则必须创建其他资源
可以对状态进行一些其他更改,但这对于示例来说已经足够了

什么是一种宁静的方式呢?

我的第一个想法是创造行动:

  • POST/record/:id/拒绝
  • POST/record/:id/validate
对我来说,它似乎是RESTful的,但太复杂了,而且,这种方法意味着让多个路由执行本质上相同的事情:更新记录对象中的一个字段

我还看到了修补方法的可能性,如:

  • PATCH/record/:id
    ,其中我检查要更新的字段是否为status,以及新值以了解要执行的操作
但当我需要对记录的其他属性执行类似的操作时,我觉得它可能会变得太复杂

我的最后一个选择,我认为可能是最好的,但我不确定它是否是RESTful,将是使用sub-ressource状态并使用PUT来更新它:

  • PUT/record/:id/status
    ,打开新值
无论前一个值是什么,切换到accepted将始终触发创建,切换到Deniked将始终触发电子邮件…等等

这些是实现宁静的方法吗?哪种方法更有意义?还有其他我没有想到的选择吗

谢谢

什么是一种宁静的方式呢

在HTTP中,您的“统一接口”是文档存储的接口。RESTAPI是一个门面,它接受具有远程创作语义(PUT/POST/PATCH)的消息,而您的实现产生了有用的工作,作为处理这些消息的副作用

我有一些记录需要处理(拒绝、验证、部分验证等),每次更改都会触发额外的操作

所以,想想我们可以如何在网络上做到这一点。我们
获取一些资源,返回的是记录信息的html表示和一组描述我们可以执行的操作的表单。所以有一个被拒绝的表单,一个被验证的表单,等等。用户选择要在浏览器中使用的正确表单,填写任何补充信息,然后提交表单。浏览器使用HTML表单处理规则将表单信息转换为HTTP请求

对于不安全的操作,表单被配置为使用POST,因此浏览器知道表单数据应该是请求消息体的一部分

请求的目标uri就是用作表单操作的任何内容——也就是说,表单的表示包含描述表单应该提交到哪里的信息

就浏览器和用户而言,目标uri可以是任何内容。因此,您可以使用单独的资源来处理验证消息和拒绝消息等

缓存在REST和HTTP中都是一个重要的概念;HTTP中有特定的缓存失效规则。因此,通常情况下,如果命令成功,您会希望使用一个目标uri来标识希望客户端重新加载的文档

所以它可能是这样的:我们
GET/record/123
,这给了我们一系列信息,以及一些描述如何更改记录的表单。因此,请填写一份表格,并成功提交,现在我们希望表格消失,或者有一套新的表格可用。因此,我们希望重新加载的是记录文档本身,表单的目标uri应该是
/record/123

(因此,API实现将负责查看HTTP请求,并找出消息的含义。它们可能都会转到单个/record/:id POST处理程序,并且该代码会查看消息体,以确定哪个内部函数应该执行该工作)

PUT/PATCH是相同的想法,只是我们不提交表单,而是发送资源本身的编辑表示。我们
获取/record/123
,更改状态(例如,更改为拒绝),然后将记录的新表示形式的副本发送到服务器进行处理。因此,服务器有责任检查其资源表示与新提供的副本之间的差异,并从中计算任何必要的副作用

我的最后一个选择,我认为可能是最好的,但我不确定它是否是RESTful的,将是使用子资源状态并使用PUT来更新它

这很好——想想你见过的任何一个网页,其中源代码有一个指向图像的链接,或者一个指向java脚本的链接。结果是两个资源而不是一个,每个资源都有单独的缓存项——这非常好,当您需要对资源的缓存进行细粒度控制时

但有一个交易——你也需要这样做