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

7
我希望在现有项目上公开一些领域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

选项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}/

这对我来说有一些微妙之处:
  1. 当只能存在一个项目时,我们返回一个数组。设置是应用程序创建的单例。
  2. 我们需要知道ID才能发出仅返回一个项目的请求
  3. 我们需要单例的ID才能进行PUT或PATCH操作

选项2:然后我的思维就朝这个方向发展:

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

PUT /settings/
PATCH /settings/

这个设计方案消除了下面提到的细微差别,并且在执行PUT或PATCH时不需要id。我认为这是最一致的方法,因为所有请求都有相同的形式。
选项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}/

这似乎不一致,因为GET 1请求的形状与UPDATE 1请求不同。它也不要求消费者执行GET以查找单例的标识符。
  1. 有没有首选的建模方式?
  2. 是否有关于建模RESTful API单例资源的良好参考资料?我目前倾向于OPTION 2,但我想知道是否有良好的资源或标准可以参考。
  3. 是否有强制要求API消费者获取资源的id,然后在更新请求中使用它的强烈理由,例如出于安全原因等?
4个回答

6
资源的ID是URL本身,不一定是Guid或UUID。URL应该唯一地标识资源,在您的情况下是“Settings”实体。但是,为了符合RESTful,您必须使用适当的rel属性在索引URL(即“/”路径)中指向此资源,以便客户端不会硬编码URL,例如:

GET /
{ ....
"links": [
       { "url" : "/settings", "rel" : "settings" }
], ...
}

访问单例资源没有具体要求,只需要Url中不包含Guid、Uuid或任何数值。


5
选项2在我看来完全符合RESTful的标准。
RESTful API的核心理念是你在操作“资源”。单词“资源”被故意留得模糊不清,以便它可以指代特定应用程序中重要的任何内容,并且API只关注如何访问内容而不管将要访问什么内容。
如果您的资源是单例的,给它分配一个ID值是没有意义的。ID在RESTful API中非常有用并且常用,但它们并不是使API RESTful的核心部分,正如您所注意到的,实际上会使访问单例资源更加麻烦。
因此,您应该放弃ID并同时拥有两个…
GET /settings/

并且

GET /settings/{id}

始终返回设置单例对象。(不需要通过id访问,但是以防万一需要时很好使用)。此外,请确保记录API端点,以便消费者不会期望一个数组 :)

关于你的问题,

我认为选项2是建模的首选方式,并且我认为强制消费者为ID进行GET实际上可能有点反模式。


4
我认为这里的混淆是因为“settings”是复数形式,但资源是单例的。 为什么不将资源重命名为“/configuration”,并选择选项2呢? 对于您的API的使用者来说,这可能会更少让人感到惊讶。

3

你可能想得太多了。在HTTP或REST中没有单例的概念。

GET /settings/ 完全可以。

顺便说一下,我们几乎无法将此与DDD相关联-至少如果您不提供有关您的领域中“设置”含义的更多上下文,则无法这样做。

这也可能是因为您正在尝试在不适当的情况下将“具有ID的实体”方法应用于设置。并非系统中所有对象都是实体。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接