RESTful API设计:轻量级连接的CRUD的最佳方式是什么?

6

抱歉标题有些拗口,难以概括这个问题。

在Facebook上,您可以点赞。在Twitter上,您可以关注人。在GitHub上,您也可以关注人并收藏存储库和代码片段。

所有这些情况都非常相似:这些连接都是轻量级的,本身不是“资源”。例如,这三个API都不公开此类连接的公共ID。

这引出了一个问题:在REST方面,暴露用于创建/查询/删除这些连接的API的“最佳”方式是什么?


Facebook提供以下API接口1:

  • GET /:id/likes用于查询对象的点赞数量(更准确地说,是喜欢该对象的用户)

  • POST /:id/likes用于点赞某个内容(代表授权用户进行操作;不需要请求正文)

  • DELETE /:id/likes用于取消点赞某个内容(代表授权用户进行操作)

查询和创建操作很合理,但DELETE操作有些“不符合RESTful”原则,因为您实际上并没有删除/:id/likes资源(一个喜欢该对象的用户数组)。

这种差异在另一种情况下也会出现2:

  • GET /me/likes/:id用于查询您是否喜欢某个内容

因此,查询您的连接是查询一个完全不同的资源,而不是创建或删除它。


GitHub 倾向于使用 /me/likes/:id 风格来关注用户和标记 repos [3]:

(请注意,GitHub 的 /user 表示已认证的用户,就像 Facebook 的 /me 一样。)

  • GET /user/starred/:owner/:repo 用于查询您是否已收藏存储库(返回 204 或 404,无论如何都没有正文)

  • PUT /user/starred/:owner/:repo 用于将存储库标记为收藏(请求中不需要正文)

  • DELETE /user/starred/:owner/:repo 用于取消对存储库的标记

这样做更加一致,但不幸的是,这将单个“星标”与群组分开:

  • GET /repos/:owner/:repo/stargazers 用于查询已标记存储库的用户

GitHub有趣的是,对于收藏代码片段 [4],使用了不同的样式:

  • GET /gists/:id/star用于查询您是否已经收藏了一个代码片段

  • PUT /gists/:id/star用于收藏一个代码片段

  • DELETE /gists/:id/star用于取消收藏一个代码片段

这保持了收藏行为与代码片段资源的关联,类似于Facebook,而不是用户资源。

GitHub没有公开展示代码片段的收藏者,但可能会有例如:

  • GET /gists/:id/stargazers查询收藏了一个代码片段的用户

虽然“stargazers”确实是一个不同的资源/名称而不是“star”,但名称相似且明显相关,并且它们都在同一资源上。

我能想到的唯一缺点是给资源命名。像 star 这样的名称可以使用,但像 followlike 这样的操作就比较棘手了。

由于Twitter API几乎不是RESTful的,因此我不打算将其作为示例。

显然,没有完全符合RESTful标准的API用于创建/查询/删除不是适当资源的事物,但我是否忽略了其他优缺点或需要考虑的其他风格?

谢谢!


你们的URL结构是怎样的,用于三种状态:喜欢、不喜欢和撤销投票(喜欢或不喜欢)? - PirateApp
2个回答

1

我喜欢/me/likes/:id风格的一件事是,点赞感觉像是单独的、可寻址的资源——例如,它们有单独的ID(恰好与我所喜欢的东西相同)。

GitHub的repo API很好地利用了这一点,用于创建/查询/删除与仓库的“star”连接,但在获取给定仓库的所有“star”连接时存在差异。

也许可以通过改变连接的寻址方式来解决这个差异:不仅依赖于对象ID,还要使用(已认证的)用户ID。例如:

  • 使用GET /:owner/:repo/stargazers查询所有收藏此仓库的用户。

  • 使用GET /:owner/:repo/stargazers/:id查询用户:id是否已经收藏了该仓库,如果指定me,则可以查询授权用户是否已经收藏了该仓库!

  • 使用PUT /:owner/:repo/stargazers/me收藏一个仓库,这只适用于授权用户。

  • 使用DELETE /:owner/:repo/stargazers/me取消收藏一个仓库,同样只适用于授权用户。

现在所有资源/操作都在一起,操作是一致的,命名也很容易。

编辑:这种方法的另一个好处是您可以轻松高效地查询其他用户是否喜欢/关注/收藏对象。

编辑: 但一个缺点是,资源现在技术上不正确了 - GET ... / stargazers 返回用户列表,但 GET ... / stargazers /:id 返回连接,而不是用户。哦,好吧?

[再次编辑以支持将 me 作为这里的:id ]


0

我认为

DELETE /:id/likes 可以用于取消点赞(代表已授权的用户)

这是有道理的,因为点赞将具有所喜欢对象的ID和您的用户ID的复合键,因此在您已经通过身份验证的登录告诉您是谁的情况下,指定ID只是多余的,并且您甚至没有权限删除其他用户的点赞。

明确指定此内容(如Aseem Kishore所建议的):

DELETE /:id/likes/me

可能会更清晰一些。


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