子资源的REST API约定

时间:2019-08-24 19:19:34

标签: rest api microservices

假设有一个事件托管服务。主持人可以使用以下方式登录并创建事件:

POST /events创建事件

GET /events获取主机创建的所有事件

GET /events/1获取ID为1的事件(如果由主机创建,否则返回错误)

现在,主持人希望为客人可以在其上进行RSVP的事件生成批量邀请代码,主持人应该能够看到响应。主机只能与来宾共享代码,并且不希望共享事件ID(因为它看起来很酷)

POST /events/1/invites,其中包含受邀者列表以生成代码

GET /event/1/invites获取被邀请者列表并查看他们的回复

GET /event/1/invites/SECRET007获取特定邀请的回复

到目前为止看起来不错,但是邀请RSVP的惯例是什么?

一个选项是:PUT /invites/SECRET007,但是问题在于它与GET对应项不匹配。

另一种选择是保留PUT API并更改所有其他邀请API

POST /invites正文:{event:1 ...},其中包含被邀请者列表以生成代码

GET /invites?event=1获取被邀请者列表并查看他们的回复

GET /invites/SECRET007获得邀请

但是在这种情况下,GET /invites毫无意义,必须始终使用事件ID来调用它。

这里遵循的正确约定是什么?

编辑:这里的重要要求是主机只能与来宾共享邀请,并且来宾应该只能使用该ID进行RSVP。

3 个答案:

答案 0 :(得分:2)

关于可能有所帮助的事情:REST并不真正理解您在此描述的“子资源”。

/invites
/invites?event=1
/invites/SECRET007

就REST而言,它们是三个完全独立的标识符,因此是三个完全独立的资源。资源标识符的拼写没有传达任何语义上的意义。这里的关系等效于这些:

/4498232d-9bf9-4405-a94d-ed5d2cfc5551
/951139d9-d5a9-43fb-ab23-ba4b383a7a11
/6b2d8b31-981d-4128-b354-776b8375decd

您使用的路由库可能会观察到标识符路径中的相似之处,并对这些信息进行一些有趣的操作,但这是在“统一接口”之后进行的实现选择。 >

例如:

DELETE /invites

如果该请求成功,则符合REST的缓存仍将保存/invites?event=1/invites/SECRET007的副本。标识符的层次结构没有任何意义。

这反过来意味着(a)您可以按自己喜欢的方式安排资源,并且(b)您可以选择任何方便的拼写方式。

具有许多“关于”同一事物的资源是正常,每个资源都有其自己的标识符。比较

  • https://stackoverflow.com/questions/57640910/rest-api-convention-for-subresource
  • https://api.stackexchange.com/2.2/questions/57640910?order=desc&sort=activity&site=stackoverflow

因此,如果您要拼写一个人类可以理解的资源标识符,那么您需要仔细考虑您的资源模型以及要提供给客户的赠品的集合。

请参见Jim Webber's 2011 talk

答案 1 :(得分:1)

我不知道这是否是“正确的约定”,但是当我遇到类似的情况时,我采取了务实的方法,并试图避免深层的资源嵌套,除非绝对必要。

我确定“绝对必要”是指子资源标识符不是全局唯一的。例如。如果您的路径是:

/events/1/invites/1
/events/1/invites/2
/events/2/invites/1

然后,邀请ID本身不足以标识确切的邀请,您需要一个包含事件ID的复合ID。

如果邀请ID 是全局唯一的-不仅是事件唯一的-那么就没有理由不能拥有根/invites资源。

/events:
  get:  
    description: list events
  post:
    description: create event
  /{id}:
    get: 
      description: get event with id {id}
    /invites:
      get:
        description: list all invites for an event
      post:
        description: create an invite for an event
/invites:
  /{id}:
    get: 
      description: get invite with id {id}
    put:
      description: update invite with id {id} (record RSVP)

如果您认为这是必需的,则实际上可以有重复的路由来访问相同的资源。例如。您可能有/events/{eventId}/invites/{inviteId}/invites/{inviteId}访问同一邀请。如果您通过活动发现邀请,则一条路线很有意义,第二条路线是直接链接到已知邀请的快捷方式。

只是我对此事的想法:)

答案 2 :(得分:0)

Microsoft在设置REST API时发布了包含指导的复杂文档。每个用例都没有详尽的规则,因此您必须做出自己的决定。似乎更喜欢使用GET / POST / PUT /events之类的CRUD模式。

查看指南:https://github.com/microsoft/api-guidelines/blob/vNext/Guidelines.md#931-nested-collections-and-properties