我为" jobs"等概念设计了一套RESTful API。工作模型如下所示:
Job: {
id: 1,
name: "Brew coffee",
status: "paused" | "running" | "finished",
progress: 0.75
}
并遵循RESTful原则,客户端通过/api/jobs
上的HTTP谓词CRUD作业。例如,新工作的初始化是
POST /api/jobs
--------------
Request body: {
name: "Push button"
}
---------------
Response status: 200 OK
Response body: {
id: 2,
name: "Cook dinner",
status: "running",
progress: 0
}
并且访问此作业
GET /api/jobs/2
--------------
Request body: {}
---------------
Response status: 200 OK
Response body: {
id: 2,
name: "Cook dinner",
status: "running",
progress: 0.5
}
我的问题是,我应该如何设计API,例如"暂停"?在我的头顶,我考虑两个 选项:
一种选择是将其设计为PATCH
请求,并直接声明我想要的结束状态,如此
PATCH /api/jobs/2
--------------
Request body: {
status: "paused"
}
---------------
Response status: 200 OK
Response body: {
id: 2,
name: "Cook dinner",
status: "paused",
progress: 0.65
}
另一种选择是将其设计为POST
请求,并声明我想要的操作,如此
POST /api/jobs/2
--------------
Request body: {
action: "pause"
}
---------------
Response status: 200 OK
Response body: {
// same as above
}
考虑到将来我可能会实施其他操作,例如" resume","优先级"," deprioritize"等等,这两个选项中的哪一个对你有用认为更好?还是有更好的做法?
答案 0 :(得分:2)
我的问题是,如何为“暂停”等操作设计API?
您如何设计网站以支持“暂停”等操作?
您可能从登录页面开始,客户端可以获取。您返回的响应可能具有作业当前状态的表示,并且还具有链接,具有用户将理解的语义注释。其中之一就是“暂停”行动。
在暂停链接之后可能会获得一个表单,其中包含许多输入字段,每个字段的语义注释以及每个字段的默认值。客户端将替换输入字段中的部分或全部值,并提交表单。
这会将表单数据发布到您指定的端点,此时您的实现将调用暂停副作用,并使用描述结果的表示进行响应。
这是要遵循的模型。 REST-API的实现是一个适配器,使您的服务看起来像是一个通用的网站。
这里的关键思想是客户端不需要事先知道要使用的URI或要使用的http方法,因为该信息被编码到服务器提供的链接的表示中。客户只需要识别并关注链接。
POST 罚款;自HTTP / 1.0以来,HTML客户端一直在使用它。如果你想提供一个“远程创作”界面,PUT和PATCH也 。
您可能想要查看Rest Causistry。确保您查看评论,这是REST真正讨论的地方。查看Fielding的Paper Tigers and Hidden Dragons ...
也很有用我还应该注意,上面还没有完全RESTful,至少我是如何使用这个术语的。我所做的就是描述服务接口,它只不过是任何RPC。为了使它成为RESTful,我需要添加超文本来介绍和定义服务,描述如何使用表单和/或链接模板执行映射,并提供代码以有用的方式组合可视化。
Matt Timmermans'评论说得对;如果您只记录客户端自行导航的一堆断开连接的端点,那么您就不会使用REST。在您不需要允许客户端和服务器独立发展的解决方案中,这也是很好。
REST适用于跨多个组织的基于网络的长期应用程序。如果您不认为需要约束,则不要使用它们。
跟进评论:
如果我们谈论的是人工操作的客户端(如浏览器),这种类型的基于导航的API组织似乎非常灵活,但我不太确定编写可以调整更改的自动客户端很容易在服务器端。 “...添加超文本来介绍和定义服务,描述如何使用表单和/或链接模板执行映射......”听起来对我来说太以人为本了。
我也遇到了麻烦。
没有人声称,使用REST API,机器消费者将神奇地能够理解API中的语义更改。如果我们想要支持现有客户端,那么我们在服务器上所做的更改必须以向后兼容的方式完成。但是 - 这是关键的想法 - 在语义和表示之间有一个额外的间接层。
要选择一个简单的示例,在具有分页的API中,消费者需要理解next page
的语义;它需要能够要求客户端处理下一页链接。但是它不需要知道关于如何表示链接,链接机制,URI或类似的东西。 通用浏览器模拟知道这些位,并为消费者做所有这些工作。
消费者仍需要了解的协议;但该协议用链接表示,而不是用URI表示。
答案 1 :(得分:1)
此问题有几个方面,选择的选项取决于您希望将哪些内容设置为优先级。
问题1)从REST角度来看哪个更好?
从严格的REST角度来看,PATCH
与{ "status": "pause" }
是正确的。 REST是代表性的国家转移。而这个解决方案最严格地符合这一点。
问题2)我应该使用' action'定向端点?
从严格的REST角度来看,答案是否定的。但是,在实践中,有很多很好的理由这样做。 严格 REST API实现的副作用之一是,您的API可以开始看起来像一个Web可访问的数据存储,而不是一个自包含的服务。发生这种情况时会发生的情况通常是越来越多的逻辑迁移到API的客户端......复杂的操作在客户端代码中实现为对多个REST操作的多次调用。
这通常不是您想要的,虽然可以通过精心设计的API来避免,但通常情况并非如此。
问题3)最佳做法是什么?
没有一个,至少不客观。具有不同用途的不同API更适合REST或面向操作的调用机制。也就是说,我很少遇到一个完全是REST的API并且没有面向行动的例程...而且大多数它们随着时间的推移都会漂移......如果没有其他原因,大多数API需要某种类型搜索功能,严格的REST没有规定。
所以,最后,我的建议是,使用REST工作,它将使您的API更容易让其他人开始......并且当行动不适合时使用面向行动的端点REST概念很好。拥有一个易于理解的动作端点比一个难以掌握的REST动作更好,它可以在幕后引发神奇的事物。
但那就像......我的观点,伙计。