REST API:需要按ID筛选资源,但未指定ID

REST API:需要按ID筛选资源,但未指定ID,rest,api-design,Rest,Api Design,假设我有一个资源/书籍,带有一个参数?author\u id=。如果没有指定author\u id参数,例如,/books而不是/books?author\u id=42,那么应该返回什么?部分基于,我决定如果你点击/books?author_id=42,如果author 42没有书,你将得到一个空集合,而不是返回404 但是,在client_id为null的情况下,我不确定是否应该以相同的方式处理此情况,即id为null的作者没有书籍,或者应该是400左右,将null视为client_id的无

假设我有一个资源/书籍,带有一个参数?author\u id=。如果没有指定author\u id参数,例如,/books而不是/books?author\u id=42,那么应该返回什么?部分基于,我决定如果你点击/books?author_id=42,如果author 42没有书,你将得到一个空集合,而不是返回404

但是,在client_id为null的情况下,我不确定是否应该以相同的方式处理此情况,即id为null的作者没有书籍,或者应该是400左右,将null视为client_id的无效值


还要注意,books是一个人为的例子,在我的例子中,如果用户点击/books,我不能简单地返回所有的书。假设只有作者才能访问他们的书籍

首先,在你上面的例子中,/books?author_id=42在某些宗教讨论中毫无疑问会出现/books/42将是id=42的get me book。相反,API应该将请求主体中的过滤器参数作为选择标准/图书将包括所有符合嵌入式筛选条件的图书,可以使用空集合

如果需要,API还可以检查某些筛选条件author是否有效,如果author不存在,则返回404。这是一个API决策,UI只知道如何与之对话并处理结果

注意到我的预测了吗?宗教讨论,伴随着严厉的批评。阅读罗伊·菲尔丁的作品和伦纳德·理查森的精辟论述

如果未指定author_id参数,则应返回什么,例如。, /书籍与/书籍相对?作者id=42

如果资源URL是有效的/books,但服务器无法提供此特定请求,那么我希望HTTP 501不作为响应代码实现。因为服务器负责不支持此功能。这是有争议的,因为有些人更喜欢4xx HTTP代码,但在我看来4xx错误状态代码指向客户端

HTTP 501的标准定义

10.5.2 501未实施服务器不支持满足请求所需的功能。这是恰当的选择 当服务器无法识别请求方法并且 无法为任何资源支持它

我已经决定,如果你点击/books?author_id=42,你将获得 如果作者42没有书籍,则为空集合,例如,返回 404

这绝对好

下一项质询—

但是,在client_id为null的情况下,我不确定是否应该这样做 以相同的方式处理此情况,即ID为null的作者 没有书,或者应该是400左右,将空视为 客户端\u id的值无效


这也很好。由于客户端发送的id无效,并且可以从客户端更正,因此400个错误请求适用于这种情况。

基本上,这取决于您,您希望如何处理此问题

我根据包含最佳实践的开发了一些RESTful API

根据他们的指导原则,REST客户机必须期望收集数据可以以页面大小返回

如果你提供分页结果,你还想提供对大集合的过滤;因此,请与作者一起筛选收藏

他们使用“OData”样式、排序和分页。我将引用实际的“过滤”一章:

$filter querystring参数允许客户端筛选 由请求URL寻址的资源集合。这个 为中的每个资源计算用$filter指定的表达式 集合,并且只有表达式计算结果为true的项 答复中包括了这些信息。表达式所针对的资源 计算结果为false或null,或引用的属性为 由于权限而不可用,将从响应中忽略 回答您的问题:这意味着您应该返回一个空的分页结果

示例:退回价格低于$10.00的所有产品

得到https://api.contoso.com/v1.0/products?$filter=价格低于10.00

$filter选项的值是一个布尔表达式


如果参数是必需的,API可能应该使用路径参数,而不是查询参数,IMO。最后,URI的结构对于遵循REST体系结构的应用程序来说并不重要,因为其意图保留在链接关系名称中。这允许服务器动态更改URI,客户端仍然能够调用进一步的操作?完整长度的URI只是一个指向单个资源的指针,而不是别的!此外,像/a/b/c这样的URI并不表示c是b的子级或a是b的父级。这只是个人的解释,不一定是真的!遵循REST架构的应用程序
体系结构根本不应该进一步解释URI,因为如果URI发生更改,这将很容易破坏客户端,而实际上链接关系名称才是最重要的。此外,这是一个针对固执己见的问题->接近理性!相反,API应该将请求主体中的过滤器参数作为选择标准。这将打破基本的REST原则,要在请求体中有参数,您必须使用POST方法,并且根据标准,您应该使用POST方法来创建资源。当然也有例外,如果搜索条件太复杂,那么对POST来说是的。但是对于这个场景,我们只有auther_id。@根据POST,Vinit不一定要创建资源。语义依赖于实现,因此不向客户端提供任何保证。这是一把瑞士军刀,如果其他行动不合适,必须使用它。可以对JSON负载进行编码,并将其放入GET请求的查询参数中。哪种方法更好是值得商榷的。一个保证开箱即用的安全性、幂等性和可缓存性,而另一个根本不提供任何保证,但最终更加灵活。@RomanVottner我上面的帖子直接基于Roy Fielding的指导原则,他在2000年提出了REST体系结构,作为其博士学位的一部分。因此,/a是资源a的集合,/a/b返回或修改单个资源a。中没有/a/b/cREST@Vinit是的,它可以放在URI中,但OP声明他想使用authorid作为查找authorid的所有书籍。由于REST只包括检索资源或单个资源的集合,因此关系操作由用户决定。如前所述,我的观点是,也许我应该更清楚,非URI数据应该在我来自MVVM竞技场的主体中,因此这是寻找进一步信息的合理位置。在OP中,/author/42引用id为42的作者。正文会说,如果服务器通常不支持HTTP方法,例如补丁,那么应该使用include books.501。如果只有某些资源不支持操作,即DELETE,那么如果在不支持该操作的资源上调用该操作,则应返回405。如果找不到给定URI的资源表示形式,404更合适,因为通常情况下,表示形式不存在不是服务器的错。@RomanVottner-如果服务器不支持修补程序,则应返回HTTP 405方法not allowed。4xx代码表示客户应对错误负责,客户应修复错误。5xx代码表示服务器负责,在服务器修复之前,同一请求不会对客户端起作用。假设/books只允许GET、PUT方法,并且客户端尝试使用补丁。现在,如果您返回HTTP 501,则客户端将停止请求,但如果您返回HTTP 405,则客户端可以使用PUT方法修复该问题。所以405代码在一个特定的http动词不被允许的情况下是好的。请再次通读我的评论,然后再通读。不是每台服务器,尤其是旧服务器都知道补丁的含义。除了补丁,我还可以选择一个专有的扩展,比如什么。客户端也可能无法将请求转换为其他方法,即当需要同时更新多个资源时