RESTful API路由设计:嵌套与非嵌套

Ern*_*sto 15 rest api-design nested-resources restful-url nested-routes

我的问题是在为API目的构建URL时嵌套资源的优势.考虑以下两种用于访问员工资源的备选方案:

/api/employees?department=1   # flat

Vs.

/api/departments/1/employees  # nested
Run Code Online (Sandbox Code Playgroud)

现在考虑开发通用库以从API访问REST资源的任务.如果所有路由都是平坦的,那么这样的REST包装器库只需要知道被访问资源的名称:

store.query('employees', {department_id:1})   =>   /api/employees?department=1
Run Code Online (Sandbox Code Playgroud)

但是,如果我们要支持嵌套路由,那么这个包装器需要知道有关嵌套模型和其他资源的额外信息,以便了解如何构建用于引用此类模型的URL.鉴于并非所有模型都嵌套在相同的父资源下,甚至一些模型根本不会嵌套,REST包装器库需要具有某种配置来描述所有这些额外的知识,否则这些知识是不需要的.

所以我的问题是:

  • API中的嵌套资源路由是否有任何实际优势?(这并不意味着最终用户使用,因此拥有更漂亮的URL可以获得更少的收益).

  • 嵌套方法是否真的比平面更好,超越美学,以便证明为支持资源URL构建缺乏统一性而引入的额外努力和复杂性?

另见:https://stackoverflow.com/a/36410780/621809

更新:重要的澄清

我从一些评论和答案中了解到,我对一个方面不够清楚:我并不反对使用/employees/5或等URL来处理单个资源/departments/1.我不认为这是嵌套的.

当我说嵌套资源时,我指的是像/departments/1/employees资源一直在另一个资源的上下文中寻址的URL .主要问题是,对于URL构建,通用库需要知道额外的东西,如"员工嵌套在部门下",但"分支不嵌套在任何东西下".如果所有资源都可以通过REST来解决,但是以平面方式解决,知道如何解决它们会更简单,更容易预测.

当您考虑它时,在数据库中,您不需要知道额外的信息,以便知道如何处理对象集合(例如RDMS中的表).您总是将员工集合称为employees,而不是departments/5/employees.

Ale*_*scu 5

如果您想进一步挖掘几个级别,会发生什么?

/api/addresses?departmentId=1&employeeId=2&addressId=3

/api/departments/1/employees/2/addresses/3

地址端点突然变得充满了参数。

此外,如果您正在查看Richardson成熟度模型级别3,则可以通过链接发现RESTful API。例如,在顶层,例如/ api / version(/ 1),您会发现有一个到部门的链接。这是在类似HAL浏览器的工具中的外观:

"api:department-query": {
  "href": "http://apiname:port/api/departments?pageNumber={pageNumber}&pageSize={pageSize}&sort={sort}"
},
"api:department-by-id": {
  "href": "http://apiname:port/api/departments?departmentId={departmentId}"
}
Run Code Online (Sandbox Code Playgroud)

(可以是最终可能以页面方式列出所有查询的查询,也可以是直接进入特定部门的参数化链接,前提是您知道ID)。

这样做的好处是,客户端仅需要知道关系(链接)名称,而服务器几乎可以自由更改关系(和资源)URL。

  • 感谢您的答复。只是跟进:扁平版本“参数膨胀”到底有什么问题?除了使用“臃肿”这个词之外,它具有查询字符串参数的事实也很糟糕,因为......?最后,我认为所有反对意见都归结为“扁平化方法会导致更丑陋的 URL”。我想弄清楚是否有超越美学的东西。 (4认同)
  • 顺便说一句,我认为即使是嵌套方法的支持者也警告不要像你举的例子那样嵌套太深。不是吗? (3认同)
  • 同样,在更详细地阅读了您的答案之后,在我的扁平化方案中,您的`/ api / departments / 1 / employees / 2 / addresses / 3`示例实际上就是`/ addresses / 3`。不是您建议的`/ api / addresses?departmentId = 1&employeeId = 2&addressId = 3`。这正是我的观点。您不需要额外的ID即可解决嵌套资源。 (2认同)

小智 5

老帖子,但对我来说并不令人满意的答案。

这取决于你的 API。如果您的数据是分层的,并且不需要在不通过其父级过滤的情况下访问资源,那么嵌套就可以(也可以不嵌套)。

如果你的 id 很长(GUID),你的层次结构很深,或者你需要访问任何资源而不被其父级过滤,那么不嵌套是一个不错的选择。

尝试有一个统一的接口,并且不要有多种方法来访问同一资源。

尝试这个链接可以更好地解释这一点: https: //www.moesif.com/blog/technical/api-design/REST-API-Design-Best-Practices-for-Sub-and-Nested-Resources/