我的另一个类似的问题,但讨论偏离了我正在讨论的问题.
假设我有一个处理费用报告(ER)的系统.您可以创建和编辑它们,添加附件以及批准/拒绝它们.
费用报告可能如下所示:
GET /er/1 => {"title": "Trip to NY", "totalcost": "400 USD", "comments": [ "john: Please add the total cost", "mike: done, can you approve it now?" ], "approvals": [ {"john": "Pending"}, {"finance-group": "Pending"}] }
看起来很好,对吗?这是费用报告文件的样子.
如果要更新它,可以执行以下操作:
POST /er/1 {"title": "Trip to NY 2010"}
如果您要批准它,您可以这样做:
POST /er/1/approval {"approved": true}
但是,如果您想要更新报告并同时批准该怎么办?我们怎么做?如果你只想批准,那么做POST
一些/er/1/approval
有意义的事情.
我们可以在URL中放置一个标志POST /er/1?approve=1
,并将数据更改作为正文发送,但该标志似乎不是RESTful.
我们也可以提交特殊领域,但这似乎也有点hacky.如果我们这样做,那么为什么不发送带有set_title
或者属性的数据add_to_cost
?
我们可以创建一个新的资源来进行更新和批准,但是(1)我想不出如何在没有动词的情况下命名它,以及(2)根据可以对哪些动作进行命名来定义资源似乎是不对的.它(如果我们添加更多动作会怎么样?)
我们可以有一个X-Approve:True | False标题,但标题似乎是错误的工具.如果不在浏览器中使用javascript,也很难获得设置的标题.
我们可以使用自定义媒体类型,application/approve+yes
但这似乎并不比创建新资源更好.
我们可以创建一个临时的"批处理操作"URL /er/1/batch/A
.然后,客户端发送多个请求,可能POST /er/1/batch/A
更新,然后POST /er/1/batch/A/approval
批准,然后POST /er/1/batch/A/status
结束批处理.在后端,服务器在某处将所有批处理请求排队,然后在收到"结束批处理"请求时在同一后端事务中处理它们.显然,它的缺点是它引入了很多复杂性.
那么,解决在单个请求中执行多个操作的问题的一般方法是什么?一般,因为很容易想象可能在同一请求中执行的其他操作:
抑制或发送通知(发送电子邮件,聊天,其他系统,等等)
覆盖一些验证(最高费用,晚宴参加者姓名)
触发在文档中没有表示的后端工作流.
它也是一个性能问题.HTTP呼叫到达网络(如果您有高延迟或连接时可能会出现问题),因此您可以制作的越少越好.
REST架构表示资源由服务器管理并由URL标识.
除此之外,/er/1/approval
您不需要使用合理的URL或模型,除非您拥有在服务器端管理和操作的批准对象或实体.在我看来,实体是费用报告本身,这意味着,/er/1
是您的URL路径.
现在,至于动词......你可以发送(POST)你喜欢的任何消息到该资源.
设定数据:
{ action: "modify", data: { purpose : "Club hopping" } }
批准:
{ action: "approve" }
新增项目:
{ action:"additem", data: { amount:72.13, category:113, note:"client dinner" }}
等等
来自Fielding的Ch5,它定义了REST,
(请求的)参数包括请求控制数据,指示请求目标的资源标识符和可选表示.
...和...
控制数据定义组件之间消息的目的,例如所请求的操作或响应的含义.它还用于参数化请求并覆盖某些连接元素的默认行为.例如,可以通过请求或响应消息中包括的控制数据来修改高速缓存行为.
因此,如果您想对资源执行多个操作,那么您应该在"控制数据"中嵌入多个消息或操作请求.在我的示例中,发布的数据将类似于:
{ action: "modify", data: { purpose : "Club hopping" } } { action: "approve" }
但你可能想要概括它,以便它是:
{ actions: [ {action:"modify", data: {...} }, { action:"approve"} ] }
服务器可以在每种特定类型的实体上处理的消息或操作由您来定义.
ps:有时REST实现使用HTTP PUT
来创建资源并POST
修改现有资源或对其进行操作.
并且:我喜欢这篇文章,如何获得一杯咖啡.