我目前正在开发REST API,尝试尽可能使用最佳实践进行设计。
我使用Symfony2 PHP框架但我的一些问题对任何REST API都有效。我猜。
从特定资源的基础设计开始:
GET /resource - Get all resources
POST /resource - Create resource
GET /resource/{id} - Get resource with id={id}
PUT|PATCH /resource/{id} - Edit the resource with id={id}
DELETE /resource/{id} - Delete the resource with id={id}
假设我的资源在更新时具有复杂的规则。
我应该如何向API使用者公开这些规则?对于日程字段,我该如何提供当前可用的不同选择?
关于Symfony服务器端部分,我遵循了本演练的大部分建议:http://williamdurand.fr/2012/08/02/rest-apis-with-symfony2-the-right-way/
我的帖子,PUT& PATCH操作由Symfony Forms处理,因此大多数规则都由Symfony约束/验证功能处理。
但表单绑定非常有限,如果用户将状态字段从 2 更改为 3 ?最好的方法是什么?
提前致谢。
答案 0 :(得分:1)
HTTP有另一个你没有使用的动词:OPTIONS
。您可以使用它来列出计划选项。
以下是关于它的博客文章:http://zacstewart.com/2012/04/14/http-options-method.html
至于更新状态,我会重复POST
并在字段中包含action
。例如:
POST
{
"type": "update",
"status": 3
}
修改后的REST:
GET /resource - Get all resources
POST /resource - Create resource
GET /resource/{id} - Get resource with id={id}
PUT|PATCH /resource/{id} - Edit the resource with id={id}
DELETE /resource/{id} - Delete the resource with id={id}
OPTIONS /resource/{id} - Retrieve options of resource with id={id}
请记住,除了GET之外,您可以在身体中传递参数,并且您可以在URL中传递任何参数以获取GET。
答案 1 :(得分:0)
我对Symfony2没有任何了解,因此我将专注于更通用的REST如何解决暴露规则问题。
为REST API的使用者提供文档。这是他们在实际使用你的API之前首先要做的事情。使用工具,从自动生成的帮助页面到第三方提供商,如Apiary.io或类似。
当消费者发送“错误”请求时创建有意义的响应:当请求参数丢失或无效时,使用正确的http响应状态代码(错误请求,冲突等)。 如果放松了REST api,它还可以包含有关出错的信息以及如何在响应正文中解决问题。 过去对我有用的是拥有一个通用的ErrorMessage实体,该实体在每个未成功的请求时返回,包含标题,错误描述和专用的更具技术性的“dev-description”,可以启用/禁用在服务器端测试/生产。 就我而言,我的消费者都知道,如果成功,他们可以获得预期的响应实体,或者如果失败,他们可以获得响应中的通用ErrorMessage实体。
如果您能够遵守规则,为什么不将这些规则作为您服务的元信息提供?例如。在我的情况下,我知道我有一组参数,每个参数都有一组可用的选项。将参数视为查询字符串中的键,将选项视为该键的值。在复杂的世界中,参数选项取决于其他参数选项,例如。在我的例子中,参数B的可用选项取决于参数A的“选择”选项。我可以通过在我的REST api中提供“元数据”资源来公开这些依赖关系,例如。一个JSON结构,列出了这些参数的所有参数和所有选项,并为每个选项添加了一个“需求”部分,如果参数xy选择了选项p和q,那么该选项只能“可用”。 这允许我的消费者 - 通过对该元数据资源的单个请求 - 在客户端创建“状态机”。我希望你能得到这张照片。
答案 2 :(得分:0)
以下是我对REST的理解 - 处理更新并向API客户端发布更新操作的完整方法。
这是基于this精彩的书籍和Fowler's有关REST的文章,其中包含File Levels of Media Type的一些内容和有关Restfull CQRS的文章。基本上你使用PUT进行更新并通过内容类型传递操作,并通过mediamedia在超媒体控件中宣传内容类型。
所有可用于资源当前状态的操作都列在超媒体控件中,这些控件通过这样的资源表示传递:
<myresource>
<status>ACTIVE</status>
<some-field with-attribute="value"/>
<some-other-field/>
<!-- other fields representing state of resource -->
<link rel = "self"
uri = "/resource/1234"/>
<link rel = "/linkrels/resource/changeStatus"
uri = "/resource/1234"
mediaType = "application/vnd.myapp+xml;domain-model=ChangeStatusCommand"/>
<link rel = "/linkrels/resource/changeSchedule"
uri = "/resource/1234"
mediaType = "application/vnd.myapp+xml;domain-model=ChangeScheduleCommand"/>
<link rel = "/linkrels/help"
uri = "/help/resource"/>
</myresource>
与mediaType的链接提供了足够的信息,允许使用哪些命令。在许多情况下,这应该是非常特定于当前资源状态的东西。例如,如果您可以将其从状态ACTIVE移至TRASHED,则命令不应命名为StatusChange
,而应命名为TrashCommand
,依此类推。