还有一个类似的question https://stackoverflow.com/questions/2001773/understanding-rest-verbs-error-codes-and-authentication对我来说,但讨论偏离了我遇到的问题。
假设我有一个处理费用报告 (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}
但是,如果您想更新报告怎么办and同时批准吗?我们该怎么做呢?如果您只想批准,那么做一个POST
类似的东西/er/1/approval
说得通。
我们可以在 URL 中添加一个标志,POST /er/1?approve=1
,并将数据更改作为正文发送,但该标志似乎不是 RESTful。
我们也可以设置要提交的特殊字段,但这似乎也有点老套。如果我们这样做了,那么为什么不发送具有以下属性的数据:set_title
or 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 调用会访问网络(如果您的延迟较高或连接不稳定,这可能会成为问题),因此您可以进行的调用越少越好。