我的资源/contracts
具有以下结构:
{
name: "Contract name",
signedAt: 123213231,
// etc.
}
基本的CRUD操作非常清楚( GET /contracts
, GET /contracts/{id}
, POST {{1 }}等),当我必须对资源进行一些具体操作时,就会产生一些疑问。
以下操作之一:
/contracts
日期将需要与签署合同的时刻(日期时间)一起更新。到目前为止,我一直在考虑这些不同的方法:
这种方法将意味着具有以下端点方法:
补丁 signedAt
并仅发布/contracts/{id}
日期signedAt
,这意味着在此之后将签署合同。
我不喜欢这种方法的原因是签名日期来自客户端,我当时认为,只要签定合同,在后端初始化该日期会更好,更一致。
完全丢弃,因为应该在服务器上设置signedAt日期 正好在标志完成的那一刻。
这种方法意味着将签名动作作为资源:
POST { signedAt: 123213231 }
在这种情况下为空,因为我们不需要传递其他任何内容,因此一旦发布,后端将负责初始化签名日期。
类似于先前的方法,在这种情况下,我将在合同资源上使用名为/contracts/{id}/sign
的查询参数:
POST action
也有一个空的正文,其中/contracts/{idContract}?action=sign
。像以前的方法一样,一旦发布后端,将负责初始化签名日期。
答案 0 :(得分:0)
我自己设计了一些Rest API,但我不是一个轻松的福音传教士,所以我的回答可能不是最好的。我建议采取以下措施:
在REST服务中为日期值创建一个自定义转换器,该转换器接受日期和其他特定字段。例如,如果您检查Google报告API,则它们允许您使用特定的日期范围,还可以使用CURRENT_WEEK,CURRENT_MONTH等。因此,您可以添加此类特定值并使用它。例如PATCH signatureAt = CURRENT_DATE,API会正确处理。
向资源添加一个布尔签名字段。用sign = true执行POST或PATCH。这样一来,您最终将可以轻松地仅查询已签名的资源;)另外,人们可能只关心是否已签名而不是已签名?
我不会使用?action = sign或/ contracts / {id} / sign,因为它们不是RESTFUL的,即使您确实使用GET和POST,您也将使用它们来创建变通方案以实现设计中应该没有动作的动作
答案 1 :(得分:0)
只需发布signedAt日期{signatureAt:123213231},这意味着在此之后将签署合同。
这组更改以一种由媒体类型标识的称为“补丁文件”的格式表示。
您可能不想考虑自己定制的媒体类型,而是要考虑一种标准格式是否合适。
例如:JSON Patch。
Content-Type: application/json-patch+json
[ { "op": "replace", "path": "signedAt", "value": 123213231 }
JSON Merge Patch是另一个合理的选择
Content-Type: application/merge-patch+json
{ signedAt: 123213231 }
据我所知,主要区别在于JSON修补程序提供了test operation,与单纯依赖validators
相比,它提供了更好的粒度控制但是您绝对正确-PATCH授予客户端代码权限以指定时间值。如果这不适合您的用例,则PATCH是框中错误的工具。
POST /contracts/{id}/sign
POST /contracts/{idContract}?action=sign
就REST / HTTP而言,这两个选择是等效的-您通过向不同资源发送不安全的请求来更新一种资源的状态。在resolving references时,这些拼写的行为会有一些细微的差异,但是作为请求目标,它对客户没有影响。
您似乎忽略了的一个选项:
POST /contracts/{id}
action=sign
这样做的好处是,成功后您将免费获得cache invalidation。
在超媒体API中,流程可能如下所示:客户端将GET
占用资源;因为尚未对资源进行签名,所以表示形式可能包括一个带有“签名”按钮的表单。表单上的操作为/contracts/{id}
。消费者通过提交表单“签署”合同-代理收集表单描述的信息,将其编码到请求正文中,然后将请求发布到服务器。服务器响应成功,并且客户端的缓存知道无效先前获取的资源副本。