RESTful API - 设计子资源

Raf*_*afa 18 rest 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}
Run Code Online (Sandbox Code Playgroud)

如您所见,有许多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}
Run Code Online (Sandbox Code Playgroud)

我的问题

Q1.被B方法考虑REST风格的?(我还在假设)

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

cas*_*lin 7

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

我不能看到两种方法中的主要缺陷,但我更倾向于方法A而不是方法A:URL更短,更容易记住,并且不需要很多参数.


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

  • 实际上,没有一个URI本身就是RESTful!它返回的内容是否符合RESTful约束.REST与干净的URI设计无关,但更多的是将客户端与服务器API分离,因此客户端应该使用返回的URI和响应来对其当前状态执行进一步的操作.不知道为什么每个人都会使用RESTful方法自动混淆URI设计.除了Fielding澄清了一些限制之外,RESTful API还必须在他的[博客文章]中进一步了解(http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven) (3认同)

Eri*_*ein 5

  1. REST对URL设计一无所获。您提出的任何URL方案都是RESTful。您应该问一下它是否是好的设计。是的,第二种方法比第一种更可取。首先是给客户带来很多噪音,给业主带来了巨大的维护问题。它还限制了未来的灵活性。

  2. 只要您清楚地记录了如何使用端点,就不会有任何陷阱。例如,嵌套端点仅返回关联元素是典型的做法,而删除嵌套元素只会删除关联,而不会删除元素本身。这种行为需要以一种方式或另一种方式进行记录。

优点:要求外部资源超出范围。


Ela*_*bak 5

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

存在依赖性

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

A在这里有一个优势,因为它非常清楚 - 当删除资源时,你删除它的所有子资源.

操作终点

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

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

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

A有一个优点,就是如何做一个动作 - 实体URL上的CRUD.B使API用户停下来,并想知道他可以对哪个URL执行哪些操作.

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

验证

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


mci*_*321 5

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

在您的域模型中,没有公司,部门就不可能存在。

现在,在您的 API 中,您公开了公司的 json 表示形式/companies/{companyId}和部门的 json 表示形式/companies/{companyId}/departments/{departmentId}

这些都是“资源”。在 HTTP/REST 术语中,资源仅表示 URL 指向的事物。所以它是“公司的 json 表示”而不是公司本身。

URL 设计本身就有点死胡同——URL 本身可以看起来像任何东西,无论它们是否可读。开发人员提出请求,根据文档*中的操作名称选择 URL。尝试为 URL 本身添加含义很快就会变得很棘手,而且随着时间的推移,实际上还会增加混乱。

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

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