Wes*_*Wes 270 rest api-design
据我所知,每个资源应该只有一个规范路径.因此,在下面的示例中,优秀的URL模式是什么?
以公司的休息代表为例.在这个假设的例子中,每个公司拥有 0个或更多部门,每个部门拥有 0个或更多员工.
没有关联公司,部门就不可能存在.
没有相关部门,员工就不能存在.
现在我会找到资源模式的自然表示.
/companies 一系列公司 - 接受新公司的接受.获取整个系列./companies/{companyId}一家公司.接受GET,PUT和DELETE/companies/{companyId}/departments接受新项目的POST.(在公司内部创建一个部门.)/companies/{companyId}/departments/{departmentId}//companies/{companyId}/departments/{departmentId}/employees/companies/{companyId}/departments/{departmentId}/employees/{empId}考虑到约束,在每个部分中,我觉得如果有点深度嵌套,这是有道理的.
但是,如果我想列出(GET)所有公司的所有员工,我的困难就来了.
最合适的资源模式将映射到/employees(所有员工的集合)
这是否意味着我应该/employees/{empId}也是因为如果是这样,那么有两个URI可以获得相同的资源?
或者整个架构可能会被展平,但这意味着员工是一个嵌套的顶级对象.
在基本级别,/employees/?company={companyId}&department={deptId}返回与最深层嵌套模式完全相同的员工视图.
URL模式的最佳实践是什么,其中资源由其他资源拥有但应该可以单独查询?
更新:请参阅下面的答案,看看我做了什么.
小智 157
我尝试了两种设计策略 - 嵌套和非嵌套端点.我发现:
如果嵌套资源具有主键并且您没有其主键,则嵌套结构要求您获取它,即使系统实际上并不需要它.
嵌套端点通常需要冗余端点.换句话说,您通常需要额外的/员工端点,以便获得跨部门的员工列表.如果您有/员工,/公司/部门/员工到底会给您带来什么?
嵌套端点不会很好地发展.例如,您现在可能不需要搜索员工,但您可能稍后会进行搜索,如果您有嵌套结构,则别无选择,只能添加另一个端点.使用非嵌套设计,您只需添加更多参数,这更简单.
有时资源可能有多种类型的父母.导致多个端点都返回相同的资源.
冗余端点使得文档更难编写,也使得api更难学习.
简而言之,非嵌套设计似乎允许更灵活和更简单的端点模式.
jer*_*myh 137
你所做的是正确的.通常,同一资源可能有许多URI - 没有规则表明您不应该这样做.
通常,您可能需要直接访问项目或作为其他内容的子集 - 因此您的结构对我有意义.
仅仅因为员工可以在部门下访问:
company/{companyid}/department/{departmentid}/employees
并不意味着他们也无法在公司下访问:
company/{companyid}/employees
哪个会让该公司的员工回归.这取决于您的消费客户需要什么 - 这就是您应该设计的内容.
但我希望所有URL处理程序使用相同的支持代码来满足请求,这样您就不会复制代码.
Wes*_*Wes 73
我把我从问题所做的事情转移到了更多人可能会看到它的答案.
我所做的是在嵌套端点上创建创建端点,修改或查询项目的规范端点不在嵌套资源上.
所以在这个例子中(只列出更改资源的端点)
POST /companies/ 创建新公司返回创建公司的链接.POST /companies/{companyId}/departments 当一个部门被放置创建新部门返回一个链接 /departments/{departmentId}PUT /departments/{departmentId} 修改一个部门POST /departments/{deparmentId}/employees 创建一个新员工返回一个链接 /employees/{employeeId}因此,每个集合都有根级资源.然而,创建是在拥有对象中.
Lon*_*yen 26
我已经阅读了上述所有答案,但似乎没有共同的策略.我在Microsoft Documents中找到了一篇关于Design API最佳实践的好文章.我想你应该参考.
在更复杂的系统中,提供允许客户端在多个级别的关系中导航的URI很有吸引力,例如
/customers/1/orders/99/products.,如果资源之间的关系在将来发生变化,则这种复杂性可能难以维护并且不灵活.相反,尝试保持URI相对简单.一旦应用程序引用了资源,就应该可以使用此引用来查找与该资源相关的项目.可以使用URI替换上述查询/customers/1/orders以查找客户1的所有订单,然后/orders/99/products按此顺序查找产品.
.
小费
避免要求资源URI比复杂URI更复杂
collection/item/collection.
red*_*ben 10
您的网址外观与REST无关.什么都可以.它实际上是一个"实现细节".就像你如何命名变量一样.它们必须具有独特性和耐用性.
不要在此浪费太多时间,只需做出选择并坚持下去/保持一致.例如,如果您使用层次结构,则可以为所有资源执行此操作.如果您使用查询参数...等,就像代码中的命名约定一样.
为什么这样 ?据我所知,"RESTful"API可以浏览(你知道......"超媒体作为应用程序状态的引擎"),因此API客户端不关心你的URL是什么样的,只要它们是有效(没有搜索引擎优化,没有人需要阅读那些"友好的网址",除了可能用于调试......)
一个URL在REST API中的好/可理解只对您作为API开发人员而不是API客户端感兴趣,就像您的代码中的变量名称一样.
最重要的是,您的API客户端知道如何解释您的媒体类型.例如,它知道:
下面是一个示例HTTP交换(实体是yaml,因为它更容易编写):
请求
GET / HTTP/1.1
Host: api.acme.io
Accept: text/yaml, text/acme-mediatype+yaml
Run Code Online (Sandbox Code Playgroud)
响应:主要资源(公司,人员,等等......)的链接列表
HTTP/1.1 200 OK
Date: Tue, 05 Apr 2016 15:04:00 GMT
Last-Modified: Tue, 05 Apr 2016 00:00:00 GMT
Content-Type: text/acme-mediatype+yaml
# body: this is your API's entrypoint (like a homepage)
links:
# could be some random path https://api.acme.local/modskmklmkdsml
# the only thing the API client cares about is the key (or rel) "companies"
companies: https://api.acme.local/companies
people: https://api.acme.local/people
Run Code Online (Sandbox Code Playgroud)
请求:链接到公司(使用之前的回复body.links.companies)
GET /companies HTTP/1.1
Host: api.acme.local
Accept: text/yaml, text/acme-mediatype+yaml
Run Code Online (Sandbox Code Playgroud)
响应:部分公司列表(在项目下),资源包含相关链接,如获取下一对公司的链接(body.links.next)另一个(模板化)搜索链接(body.links.search)
HTTP/1.1 200 OK
Date: Tue, 05 Apr 2016 15:06:00 GMT
Last-Modified: Tue, 05 Apr 2016 00:00:00 GMT
Content-Type: text/acme-mediatype+yaml
# body: representation of a list of companies
links:
# link to the next page
next: https://api.acme.local/companies?page=2
# templated link for search
search: https://api.acme.local/companies?query={query}
# you could provide available actions related to this resource
actions:
add:
href: https://api.acme.local/companies
method: POST
items:
- name: company1
links:
self: https://api.acme.local/companies/8er13eo
# and here is the link to departments
# again the client only cares about the key department
department: https://api.acme.local/companies/8er13eo/departments
- name: company2
links:
self: https://api.acme.local/companies/9r13d4l
# or could be in some other location !
department: https://api2.acme.local/departments?company=8er13eo
Run Code Online (Sandbox Code Playgroud)
因此,当您看到链接/关系方式如何构建URL的路径部分时,您的API客户端没有任何价值.如果您正在将您的URL结构作为文档传达给您的客户,那么您不会根据" Richardson的成熟度模型 " 进行REST(或至少不是3级)
我不同意这种道路
GET /companies/{companyId}/departments
Run Code Online (Sandbox Code Playgroud)
如果你想获得部门,我认为最好使用/ departments资源
GET /departments?companyId=123
Run Code Online (Sandbox Code Playgroud)
我想你有一个companies表和一个departments表然后用你用你编程语言映射它们的类.我还假设部门可以连接到除公司之外的其他实体,因此/部门资源很简单,将资源映射到表也很方便,而且您不需要那么多的端点,因为您可以重用
GET /departments?companyId=123
Run Code Online (Sandbox Code Playgroud)
例如,对于任何类型的搜索
GET /departments?name=xxx
GET /departments?companyId=123&name=xxx
etc.
Run Code Online (Sandbox Code Playgroud)
如果你想创建一个部门,那么
POST /departments
Run Code Online (Sandbox Code Playgroud)
应使用资源,请求正文应包含公司ID(如果部门只能链接到一家公司).
| 归档时间: |
|
| 查看次数: |
78118 次 |
| 最近记录: |