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

Ase*_*ore 6 api rest web-services github-api facebook-graph-api

(请原谅问题标题;很难总结这个问题。)

在 Facebook 上,你的like东西。在推特上,你们这些follow人。在 GitHub 上,您还可以看到follow人员、star存储库和要点。

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

这就提出了一个问题:公开用于创建/查询/删除这些连接的 API 的“最佳”(就 REST 而言)方法是什么?


Facebook 的做法 [ 1 ]:

  • GET /:id/likes查询某个对象的喜欢程度(更准确地说,喜欢该对象的用户)

  • POST /:id/likes喜欢某事(代表经过授权的用户;不需要请求正文)

  • DELETE /:id/likes不喜欢某些东西(代表经过授权的用户)

查询和创建是有意义的,但DELETE有点“非 RESTful”,因为您实际上并没有删除/:id/likes资源(喜欢该对象的用户数组)。

这种差异在另一种情况下也表现出来[ 2 ]:

  • GET /me/likes/:id询问你是否喜欢某事

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


GitHub倾向于/me/likes/:id以下用户和明星存储的风格[ 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有效,但诸如follow或 之类的操作like则更棘手。


(不费心将 Twitter API 作为示例,因为它几乎不是 RESTful。)

显然没有完美的 RESTful API 来创建/查询/删除不合适的资源,但是还有其他我没有看到的优点/缺点,或者需要考虑其他样式吗?

谢谢!

Ase*_*ore 1

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

GitHub 的存储库API 很好地使用它来创建/查询/删除存储库的“星”连接,但在获取给定存储库的所有“星”连接时存在差异。

也许可以通过更改处理这些连接的方式来解决此差异:不要仅依赖对象 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此处。]