RESTful API - 设计子资源

时间:2016-10-13 14:25:07

标签: rest restful-architecture restful-url

我正在设计一个RESTful API,我想出了与子资源相关的问题。

我看到其他API使用完整的URL来操作子资源。以Company has DepartmentsDepartment has Employees

为例

一开始我虽然关于实现所有可能的URL。导致以下结果:

接近A

01. ### COMPANY URLS ###
02. DELETE /companies/{companyId}
03. GET    /companies/{companyId}
04. POST   /companies
05. PUT    /companies/{companyId}
06. 
07. ### DEPARTMENT URLS ###
08. DELETE /companies/{companyId}/departments/{departmentId}
09. GET    /companies/{companyId}/departments/{departmentId}
10. POST   /companies/{companyId}/departments
11. PUT    /companies/{companyId}/departments/{departmentId}
12. DELETE /departments/{departmentId}
13. GET    /departments/{departmentId}
14. PUT    /departments/{departmentId}
15. 
16. ### EMPLOYEE URLS ###
17. DELETE /companies/{companyId}/departments/{departmentId}/employees/{employeeId}
18. GET    /companies/{companyId}/departments/{departmentId}/employees/{employeeId}
19. POST   /companies/{companyId}/departments/{departmentId}/employees
20. PUT    /companies/{companyId}/departments/{departmentId}/employees/{employeeId}
21. DELETE /departments/{departmentId}/employees/{employeeId}
22. GET    /departments/{departmentId}/employees/{employeeId}
23. POST   /departments/{departmentId}/employees
24. PUT    /departments/{departmentId}/employees/{employeeId}
25. DELETE /employees/{employeeId}
26. GET    /employees/{employeeId}
27. PUT    /employees/{employeeId}

正如您所看到的,有许多URL执行相同的操作。示例:08重复12; 09重复13; 17是重复的21和25 ...

我想删除重复但保持一致性。因此,重新设计API时要考虑原则sup-resources are fine but sub-sub-resources are not。结果如下:

方法B

01. ### COMPANY URLS ###
02. DELETE /companies/{companyId}
03. GET    /companies/{companyId}
04. POST   /companies
05. PUT    /companies/{companyId}
06. 
07. ### DEPARTMENT URLS ###
08. DELETE /departments/{departmentId}
09. GET    /departments/{departmentId}
10. GET    /companies/{companyId}/departments
11. POST   /companies/{companyId}/departments
12. PUT    /departments/{departmentId}
13. 
14. ### EMPLOYEE URLS ###
15. DELETE /employees/{employeeId}
16. GET    /employees/{employeeId}
17. GET    /departments/{departmentId}/employees
18. POST   /departments/{departmentId}/employees
19. PUT    /employees/{employeeId}

我的问题

Q1。 方法B 被认为是RESTful吗? (我还在假设)

Q2。是否存在陷阱方法B 我应该考虑,假设还提供了文档?

如果您指向方法B 之后的其他API,则获得积分。

修改

Elad Tabak提供了很好的见解。

我喜欢使用方法B 的一些API:

https://developers.google.com/youtube/v3/docs/

https://developer.github.com/guides/getting-started/

https://dev.twitter.com/rest/public

4 个答案:

答案 0 :(得分:6)

如果你不打破Roy Thomas Fielding论文chapter 5中定义的REST约束,那么这两种方法都可以被视为RESTful:

我看不出两种方法都存在重大缺陷,但我更喜欢方法B 而非方法A :网址更短,更容易记住,参数不多是必需的。

加分: SpotifyFacebook API遵循此方法。当然还有其他API,但这些是我想到的。

答案 1 :(得分:5)

  1. REST没有提及网页设计。您提出的任何URL方案都是RESTful。你应该问它是不是很好的设计。是的,第二种方法比第一种方法更优选。第一个是客户的大量噪音和业主的巨大维修问题。它还限制了未来的灵活性。

  2. 我知道没有明显的陷阱,只要您清楚地记录如何使用端点。例如,嵌套端点通常只返回关联的元素,DELETEing嵌套元素只会删除关联,而不会删除元素本身。这种行为需要以某种方式记录下来。

  3. 奖励积分:要求外部资源超出范围。

答案 2 :(得分:5)

设计方法提出了在两者之间进行选择时需要考虑的几个问题:

存在依赖

A 中,非常直观,当您删除公司时,您还会删除其所有子资源 - 部门和员工。 在 B 中,API用户需要考虑一下此类操作的时刻 - 我是否需要调用所有员工的删除,或者是否足以删除公司?当然,这可以记录下来,但仍然不是直截了当的。

A 在这里有优势,因为它非常清楚 - 删除资源时,会删除所有子资源。

操作终点

它引发的另一个问题 - 如何更新实体?从哪个终点?

如果我想删除一名员工,是否足以使用一组新员工更新公司?或者我必须删除员工吗?

或者说我想将员工从一家公司改为另一家公司。在 B ,理论上我可以用公司字段更新员工,并完成它。在 A 中没有这样的方式......

A 有一个优势,即如何执行操作非常直接 - 实体网址上的CRUD。 B 会让API用户停下来,并想知道他可以针对哪个网址执行哪项操作。

但与此同时, B 的优势在于更改实体的“育儿”更容易(在相关的情况下)。

<强> 验证

A 中,您必须验证URL参数匹配,因为用户可以向员工ID提供错误的公司或部门。 在 B 中没有这样的问题。

答案 3 :(得分:3)

所以这可能听起来有些疯狂,但是没有像“子资源”这样的东西。在HTTP / REST中。

在您的域模型中,某个部门在没有公司的情况下无法存在。

现在,在您的API中,您可以在/companies/{companyId}公开公司的json表示,并在/companies/{companyId}/departments/{departmentId}公开部门的json表示。

这些都是&#39;资源&#39;。 HTTP / REST术语中的资源仅表示URL指向的内容。因此,它是公司的“json”代表。不是公司本身。

网页设计本身就是一个死胡同 - 网址本身看起来像任何东西,如果它们是否可读则无关紧要。开发人员根据文档*中的操作名称发出请求,选择URL。试图为URL本身添加意义很快就会变得棘手,实际上随着时间的推移会增加混乱。

最好花时间在文档上,而不是试图让人们推断域行为。

*或超媒体(例如https://github.com/kevinswiber/siren