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

时间:2017-03-07 22:54:39

标签: rest api 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

选项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. 当只有1项CAN和EVER存在时,我们返回一个数组。设置是应用程序创建的单例。
  2. 我们需要知道id才能发出仅返回1项
  3. 的请求
  4. 我们要求单身人士的身份只是为了PUT或PATCH它
  5. 选项2:我的思绪朝这个方向发展:

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

    此设计消除了下面提到的细微差别,并且不需要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}/
    

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

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

4 个答案:

答案 0 :(得分:5)

Resource的ID是Url本身,不一定是GuidUUIDUrl应该唯一 ID 包含Resource,在您的情况下为Settings实体。 但是,为了成为RESTfull,您必须在索引Url(即/路径)中使用适当的rel属性指向此资源,这样客户端就不会对Url进行硬编码,例如:

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

除了Url之外,没有任何细节可以访问单个资源,不包含Guid,Uuid或任何其他数值。

答案 1 :(得分:2)

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

RESTful API背后的核心理念是您正在操纵“资源”。 “资源”一词有意留下含糊不清的内容,以便它可以引用对特定应用程序很重要的内容,以便API可以只关注 如何访问内容,而不管是什么将访问内容。

如果您的资源是单身,则将ID值归属于它是没有意义的。 ID非常有用,并且通常在RESTful API中使用,但它们是使REST RESTful的核心部分,并且正如您所注意到的,实际上会使访问单例资源更加麻烦。

因此,您应该取消ID并同时使用

GET /settings/

GET /settings/{id}

始终返回设置单例对象。 (不需要access-by-id,但是如果有人尝试的话,这很好)。此外,请务必记录您的API端点,以便消费者不要指望数组:)

回复:你的问题,

我认为选项2是建模的首选方式,我相信要求你的消费者为id做一个GET实际上有点反模式。

答案 2 :(得分:2)

我认为这里的混淆是因为设置这个词是复数,但资源是单身。

为什么不将资源重命名为/configuration并使用选项2?

对于API的消费者而言,这可能不那么令人惊讶了。

答案 3 :(得分:2)

你可能正在思考它。 HTTP或REST中没有单例的概念。

GET /settings/完全没问题。

顺便说一下,我们很难将其与DDD联系起来 - 至少如果你没有提供关于设置在你的域中的含义的更多背景信息,那么至少不会这样做。

如果不合适,您可能还想尝试在设置上添加“带ID的实体”方法。并非系统中的所有对象都是实体。