据我所知,每个单独的资源应该只有一个规范路径。那么在下面的例子中,好的URL模式是什么呢?
以公司的rest表示为例。在这个假设的例子中,每个公司拥有0个或多个部门,每个部门拥有0个或多个员工。
没有关联公司,一个部门就不能存在。
一个员工的存在离不开一个相关的部门。
现在我发现资源模式的自然表示是。
公司的集合-接受新公司的POST。获取整个集合。
/companies/{companyId}单个公司。接受GET, PUT和DELETE
/companies/{companyId}/departments接受新项的POST。(在公司内部创建一个部门。)
/公司/ {companyId} / {departmentId} / /部门
/公司/ / {departmentId} / {companyId} /部门员工
/公司/ {companyId} /部门/ {departmentId} /员工/ {empId}
考虑到每个部分的限制,我认为这是有意义的,如果嵌套有点深的话。
然而,如果我想列出(GET)所有公司的所有员工,我的困难就来了。
它的资源模式将最紧密地映射到/employees(所有员工的集合)
这是否意味着我应该有/employees/{empId},因为如果是这样,那么就有两个URI来获得相同的资源?
或者可能整个模式应该是扁平的,但这意味着雇员是一个嵌套的顶级对象。
在基本层面/员工/?company={companyId}&department={deptId}返回与嵌套最深的模式完全相同的员工视图。
对于资源属于其他资源,但应该可以单独查询的URL模式,最佳实践是什么?
url的外观与REST无关。任何事情都可能发生。它实际上是一个“实现细节”。就像给变量命名一样。它们所需要的是独特和耐用。
不要在这上面浪费太多时间,只要做出选择并坚持下去。例如,如果你采用层次结构,那么你对所有资源都这样做。如果你使用查询参数…等等,就像代码中的命名约定一样。
为什么?据我所知,“RESTful”API是可浏览的(你知道…“超媒体作为应用程序状态的引擎”),因此API客户端并不关心你的url是什么样的,只要它们是有效的(没有SEO,没有人需要阅读这些“友好的url”,除了可能是为了调试…)
REST API中的URL有多好/易懂,只对作为API开发人员的你感兴趣,而不是API客户端,就像代码中的变量名一样。
最重要的是你的API客户端知道如何解释你的媒体类型。
例如,它知道:
您的媒体类型有一个links属性,它列出了可用的/相关的链接。
每个链接都由一个关系来标识(就像浏览器知道link[rel="stylesheet"]意味着它是一个样式表,或者rel=favico是一个指向favicon的链接…)
它知道这些关系的含义(“公司”指的是公司列表,“搜索”指的是在资源列表上进行搜索的模板url,“部门”指的是当前资源的部门)
下面是一个HTTP交换的示例(正文在yaml中,因为它更容易编写):
请求
GET / HTTP/1.1
Host: api.acme.io
Accept: text/yaml, text/acme-mediatype+yaml
响应:主要资源的链接列表(公司,人,等等…)
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
请求:链接到公司(使用之前的响应的body.links.companies)
GET /companies HTTP/1.1
Host: api.acme.local
Accept: text/yaml, text/acme-mediatype+yaml
Response:一个公司的部分列表(在项目下),资源包含相关链接,如链接得到下一对公司(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
你可以看到,如果你用链接/关系的方式构造url的路径部分对API客户端没有任何价值。如果你把你的url结构作为文档传达给你的客户端,那么你就不是在使用REST(或者至少不是按照“Richardson的成熟度模型”的第三级)。