Luk*_*uke 6 api rest api-design http
我有2个资源:courses
和professors
.
A course
具有以下属性:
A professor
具有以下属性:
所以,你可以说课程有一位教授,一位教授可能有很多课程.
如果我想获得所有课程或所有教授,我可以:GET /api/courses
或GET /api/professors
分别.
当我想要获得某位教授所教授的所有课程时,我的困境就来了.
我可以使用以下任何一种方法:
GET /api/professors/:prof_id/courses
GET /api/courses?professor_id=:prof_id
我不确定要使用哪个.
目前,我正在使用后者的增强形式.我的理由是,如果我想添加过滤/排序标准,它更具可扩展性.
我实际上是在编码/嵌入JSON字符串到查询参数中.因此,(解码)示例可能是:
GET /api/courses?where={professor_id: "teacher45", year: 2016}&order={attr: "topic", sort: "asc"}
Run Code Online (Sandbox Code Playgroud)
上述请求将检索教授使用2016年提供的professor_id教授(或当前正在)教授的所有课程,按照主题标题按升序ASCII顺序排序.
我从来没有见过有人这样做过,所以我想知道我是不是做了些蠢事.
是否有使用查询字符串与资源路径进行过滤条件的标准做法?过去做过什么更大的API?是否可以接受或鼓励同时使用两种范例(使两个端点都可用)?如果我确实应该使用第二种范式,除了编码JSON之外,还有更好的组织方法吗?有没有人在他们的查询字符串中看到使用JSON的另一个公共API?
编辑基于意见较少.(看评论)
正如前面的评论中已经解释的那样,REST 并不关心标识唯一资源的链接的实际形式,除非违反了RESTful 约束或超文本传输协议 (HTTP) 本身。
关于查询或路径(甚至矩阵)参数的使用完全取决于您。何时使用什么没有固定的规则,只是个人喜好。
我喜欢使用查询参数,特别是当该值是可选的并且不需要像 JAX-RS 这样的大量框架时,即允许定义默认值。查询参数通常被认为是为了避免缓存响应,但这更多的是都市传说而不是事实,尽管某些实现可能仍然会忽略对包含查询字符串的 URI 进行缓存的响应。
如果参数定义了诸如特定风味属性(即汽车颜色)之类的东西,我更喜欢将它们放入矩阵参数中。它们也可以出现在 URI 的中间,即/api/professors;hair=grey/courses
可以返回头发颜色为灰色的教授持有的所有资源。
根据我的理解,路径参数是应用程序满足请求所需的强制参数,否则将不会首先在服务端调用相应的方法处理程序。通常这是一些资源标识符,例如分配给特定实体的表行 ID 或 UUID。
在描述关系时,我通常从 1:n 关系的 1 部分开始。如果我面对的是:n 关系,就像您与教授的情况一样,我通常会从可能更容易存在的实体开始。即使教授不举办任何讲座(在特定术语中),他仍然是教授。如果没有教授,课程就不再是课程,所以我会把教授放在课程之前,尽管就 REST 而言,课程仍然是很好的顶级资源。
因此我会改变你的查询
GET /api/courses?where={professor_id: "teacher45", year: 2016}&order={attr: "topic", sort: "asc"}
Run Code Online (Sandbox Code Playgroud)
像这样的东西:
GET /api/professors/teacher45/courses;year=2016?sort=asc&onField=topic
Run Code Online (Sandbox Code Playgroud)
我稍微改变了你的字段的语义,因为年份属性可能更适合课程而不是教授资源,因为教授已经通过教授 ID 简化为单一资源。然而,这些课程应该仅限于 2016 年举办的课程。由于排序是相当可选的,并且可能指定了默认值,因此这是我放入查询参数部分的完美候选者。排序依据的字段与排序本身相关,因此也属于查询参数。我将年份放入矩阵参数中,因为这是课程本身的特定属性,例如汽车的颜色或汽车的制造年份。
但正如之前所解释的,这是相当固执己见的,可能与您或其他人的观点不符。