REST过滤和知道结果是单数的最佳实践:列表还是单个?

时间:2019-02-26 16:41:48

标签: rest

各种REST实践建议(例如123)在端点中使用复数形式,结果始终是对象列表,除非已通过特定对象过滤了该对象值,例如/users/123查询参数用于过滤列表,但是仍然会生成列表。我想知道我的案子是否应该“放弃”这些最佳做法。

下面我们以汽车为例。
我有一个充满汽车的数据库,每个数据库都有一个BuildNumber(“ Id”),还有一个模型和制造年份,这是唯一的组合。然后,如果我查询/cars/并搜索特定的模型和年份,例如/cars?model=golf&year=2018,根据我的上一句话,我知道我的检索将始终包含单个对象,而不会包含多个对象。但是,我的结果仍然是一个仅包含一个对象的列表。

在这种情况下,最好的做法是如上所述,即使必须返回一个对象,也必须从列表中提取该对象。

  1. 坚持最佳做法并导出列表
  2. 再创建一个端点/car/并使用查询参数?model=golf&year=2018,这些参数主要用于列表中的过滤,并且结果是单个对象,因为端点是奇异的。

我问这个问题的原因仅仅是为了使操作更简洁:我100%确信我的GET请求将导致单个对象,但仍然必须执行操作以从列表中提取它。这些步骤应该是不必要的。除此之外,就我而言,我不知道唯一标识符,因此cars/123来检索特定汽车不是一种选择。我知道,但是,过滤器将导致一个对象和一个特定对象的总和。附加步骤简直是多余的。


1:https://docs.microsoft.com/en-us/azure/architecture/best-practices/api-design
2:https://blog.mwaysolutions.com/2014/06/05/10-best-practices-for-better-restful-api/
3:https://medium.com/hashmapinc/rest-good-practices-for-api-design-881439796dc9

3 个答案:

答案 0 :(得分:1)

正如您特别要求的有关REST的最佳做法:

REST根本不在乎您如何指定URI,或者根本不在URI中使用语义上有意义的标记。此外,客户端应该never expect a certain URI to return a certain type,而应依靠内容类型协商来告知服务器客户端支持的所有功能。

此外,您不应该从面向对象的角度来考虑REST,而应该从affordance and statemachines的角度来考虑,在REST中,向客户提供所需的所有信息,以便就下一步的工作做出明智的决定。

此处提供的最佳示例可能是仔细研究Web及其对HTML页面的处理方式。您如何过滤特定的汽车,以及如何将其展示给您? Web中使用的相同概念也适用于REST,因为它们都使用相同的交互模型。关于您的汽车样本,API首先应返回一些控制结构,这些结构将告知客户如何形成请求以及可以过滤哪些选项。在HTML中,这是通过表单完成的。对于基于非HTML的REST API,应定义专用的媒体类型,以将相同的方法转换为非HTML结构。在将请求发送到服务器时,您的客户端会将其支持的所有受支持的媒体类型包含在Accept HTTP标头中,该标头会通知服务器有关客户端功能的信息。媒体类型只是关于如何处理此类有效载荷的人类可读规范。此类规范may include hints on type information a link relation might return。为了获得广泛使用的媒体类型,应将它们定义为尽可能通用的。除了可以定义汽车专用的媒体类型以外,使用现有的或定义新的通用数据容器格式(类似于HTML)可能更方便。

这里提到的所有步骤都应该帮助您设计和实现一个可以自由发展而又无需冒着破坏客户的风险的API的需求,此外,API还具有可扩展性,并且将互操作性问题降到最低。

不幸的是,您的问题针对的是与IMO完全不同的东西,与RPC更相关的东西。您基本上可以通过终结点上的HTTP调用通用方法,类似于SOAP,RMI或CORBA。在这里,是否遵守HTTP操作的语义只是次要的。即使您达到了Richardson Maturity Model (RMM)的第3级,也并不意味着您符合REST。如果服务器在响应中进行任何更改,您的客户端可能仍会中断。 RMM甚至根本不考虑媒体类型,因此我认为它没有用。

但是,无论您使用的是(true)REST还是RPC / CRUD客户端,如果都是检索单个项而不是将其馈送到集合中,则应该优先考虑检索单个项的URI而不是其数据正如Evert也建议的那样,直接将其添加到集合中。尽管大多数人似乎都在关注服务器性能和往返时间,但实际上它在缓存方面非常优雅。诸如prefetch之类的其他某些链接关系名称可能会通知客户端,它可能会提早获取目标有效负载,因为很有可能接下来将请求其内容。通过缓存,甚至不必触发请求或将请求发送到服务器进行处理,这可能是您可以获得的最佳性能提升。

答案 1 :(得分:0)

1)如果您使用查询,例如cars / where ...-使用CARS

2)如果您想使用CAR-制作方法GetCarById

答案 2 :(得分:0)

您可能无法得到一个完美的答案,因为所有这些都将有些主观,而且通常会以不同的方式出现。

我对此的一般想法是,系统中的每个项目都将有其自己的唯一URL,例如/cars/1234。这种情况总是单数。

但是此特定项目可能会在集合和搜索结果中显示为成员。当/cars/1234出现在其中时,它们将始终显示为具有1个项目(或0或更多,取决于查询)的列表。

我认为这最终是最可预测的。

不过,在我的情况下,如果汽车出现在搜索或串谋中,则仍会显示“真实网址”。