如何为单个资源建模RESTful API?

gta*_*rga 3 api rest domain-driven-design

我希望在现有项目之上公开一些域RESTful API.我需要建模的实体之一有一个文档:设置.设置是使用应用程序创建的,是一个单例文档.我想通过精心设计的基于资源的RESTful API来公开它.

通常,在为具有许多项的资源建模API时,其类似于:

GET /employees/ <-- returns [] of 1-* items
GET /employees/{id}/ <-- returns 1 item
POST /employees/ <-- creates an item
PUT /employees/{id}/ <-- updates all fields on specific item
PATCH /employees/{id}/ <-- updates a subset of fields specified on an item
DELETE /employees/{id}/ <-- deletes a specific item
Run Code Online (Sandbox Code Playgroud)

选项1:如果我以相同的方式建模设置,则构建以下API:

GET /settings/ <-- returns [] of 1-* items
[{ "id": "06e24c15-f7e6-418e-9077-7e86d14981e3", "property": "value" }]

GET /settings/{id}/ <-- returns 1 item
{ "id": "06e24c15-f7e6-418e-9077-7e86d14981e3", "property": "value" }

PUT /settings/{id}/
PATCH /settings/{id}/
Run Code Online (Sandbox Code Playgroud)

这对我来说有一些细微差别:

  1. 当只有1个项目CAN和EVER将存在时,我们返回一个数组.设置是应用程序创建的单例.
  2. 我们需要知道id才能发出请求只返回1项
  3. 我们需要单例的id来PUT或PATCH它

方案2:我的思绪然后朝着这个方向前进:

GET /settings/ <-- returns 1 item
{ "id": "06e24c15-f7e6-418e-9077-7e86d14981e3", "property": "value" }

PUT /settings/
PATCH /settings/
Run Code Online (Sandbox Code Playgroud)

此设计消除了下面提到的细微差别,并且不需要ID到PUT或PATCH.这对我来说是最一致的,因为所有请求都具有相同的形状.

选项3:另一种选择是将id添加回PUT和PATCH以要求它进行更新,但是API用户必须执行GET才能获得单例的id:

GET /settings/ <-- returns 1 item
{ "id": "06e24c15-f7e6-418e-9077-7e86d14981e3", "property": "value" }

PUT /settings/{id}/
PATCH /settings/{id}/
Run Code Online (Sandbox Code Playgroud)

这似乎不一致,因为GET 1与UPDATE 1请求的形状不同.它也不需要消费者执行GET来查找单例的标识符.

  1. 有没有一种首选的方式来模拟这个?
  2. 有没有人为单例资源建模RESTful API有任何好的参考资料?我目前倾向于选择2,但我想知道是否有好的资源或标准我可以研究.
  3. 是否有令人信服的理由要求API使用者为资源的ID进行GET,然后在更新请求中使用它,可能出于安全原因等?

Ped*_*lho 5

据我所知,选项 2 是完全 RESTful 的。

RESTful API 背后的核心思想是您正在操纵“资源”。“资源”一词故意保持模糊,以便它可以指代对特定应用程序重要的任何内容,并且 API 可以只关注如何访问内容,而不管将访问什么内容。

如果您的资源是单例,则为其赋予 ID 值是没有意义的。ID 非常有用并且常用于 RESTful API,但它们并不是RESTful API 的核心部分,而且正如您所注意到的,它们实际上会使访问单例资源变得更加麻烦。

因此,您应该取消 ID 并同时拥有 ID

GET /settings/
Run Code Online (Sandbox Code Playgroud)

GET /settings/{id}
Run Code Online (Sandbox Code Playgroud)

始终返回设置单例对象。(按 ID 访问不是必需的,但最好有以防万一有人尝试)。另外,请务必记录您的 API 端点,这样消费者就不会期望有一个数组:)

回复:你的问题,

我相信选项 2 将是对此进行建模的首选方式,并且我相信要求您的消费者对 id 进行 GET 实际上在某种程度上是一种反模式。


Con*_*enu 5

它的ID Resource是它Url自己,不一定是GuidUUID.本Url应唯一ID entify的Resource,你的情况的Settings实体.但是,为了成为RESTfull,您必须/使用适当的rel属性在索引Url(即路径)中指向此资源,因此客户端不会对Url进行硬编码,例如:

GET /
{ ....
"links": [
       { "url" : "/settings", "rel" : "settings" }
], ...
}
Run Code Online (Sandbox Code Playgroud)

除了Url不包含Guid,Uuid或任何其他数值之外,没有特定的访问单例资源.