API的URL设计

9
我正在为我们的后端开发私有api。
我有具有关联的集合(collections)。
每个集合都可以被请求、分页,你也可以要求关联并对这些关联进行分页。
我们还不确定该使用哪种URL设计……我们正在考虑:
  • /users.json?per_page=10&association=parts,auditions&parts_per_page=5&auditions_per_page=5

  • /users.json?per_page=10&association[]=parts&association[]=auditions&parts_per_page=5&auditions_per_page=10

  • /users.json?per_page=10&association[auditions]=true&association[parts][per_page]=5

你觉得呢?你会选择哪一个?为什么?其中一个看起来不像有效的URL方案吗?
谢谢!
3个回答

14

我的答案是:/users.json。HTTP优化了大颗粒度超媒体传输;缓存是其中的一部分,上述任何URI方案都不太友好。

例如,Squid是一个流行的HTTP缓存,默认情况下不会缓存任何具有查询字符串的URL。此外,许多客户端甚至服务器和中介生成和使用未定义顺序的查询字符串参数;也就是说,“?a=3&b=5”可以任意重写为“?b=5&a=3”。但是,对于HTTP缓存,顺序很重要,即使这两个页面具有相同的内容,它们也将被单独缓存。随着参数的增加,这个问题呈指数级增长。

您应该设计您的资源(及其表示)以利用两种相反但互补的技术的缓存:

  1. 将分散和部分表示组合成较大的统一表示,并且
  2. 在沿着缓存边界(倾向于是事务边界)分离大型、统一的表示形式,但相关联的超链接。

在您的情况下,步骤1意味着将关联和部分组合成“用户”表示形式,没有选项供客户端配置哪些及其数量。这将使您能够积极地缓存单个响应表示,而不会因所有查询字符串选项的组合爆炸而过载您的(和他们的)缓存。

步骤2意味着将/users.json分为单独的“用户”实体,每个实体都有一个“关联”资源和一个“部件”资源,即/users/{id}/users/{id}/associations/users/{id}/parts。然后,“/users”资源返回到各个“/users/{id}”资源的超链接数组,并且每个“/users/{id}”表示形式包含指向其关联和部分的超链接(那部分更加灵活-直接将关联和部分嵌入到用户资源中可能更适合您的应用程序)。这将使您能够积极地缓存每个“需求”资源的响应,而无需缓存整个数据库。

然后,你的用户会尖叫着说:"这样做会增加10倍的网络流量!" 你冷静地回应道:"不,这只是1/10的网络流量,因为十次请求中有九次所请求的资源已经存在于你的客户端(浏览器)缓存中(当它们不存在时,因为它们已经存在于服务器端的缓存中,所以这只占用了1/10的计算资源,而当它们在那里也不存在时,我们使用智能缓存避免了大规模的请求)。"

当然,如果"/users"资源每天都会被一百万个新访问者使用,那么你的优化路径可能会有所不同。但根据你的示例URI方案,似乎并非如此。

嘿,fumanchu,感谢回复!我不明白为什么我的URL没有进行缓存优化?这些调用不会在浏览器中执行,而是在服务器端执行(我可以根据url + params轻松缓存)。我不想为每个关联分离调用(这就是为什么我的API不完全符合RESTful的原因),这意味着需要多次调用才能获取一些信息,即使使用缓存也不行... - Mike
我在我的回复中添加了我的响应(以斜体形式)。 - fumanchu

3

嘿,马库斯,感谢你的跟进并将其标记为restful-url,我没有找到任何有关在API中使用数组的有用帖子。而且我不确定这个API是否可以归类为restful API,我们不想把所有东西都嵌套起来...否则,要从集合中获取2个关联,我们必须进行2个调用,我们真的不想这样做。 - Mike

1

我会选择第一个。我不喜欢在URL中看到[]符号,个人认为这样会让客户更难使用和理解。以下是一些建议的更改。

1)由于association似乎是一个数组,可以将其改为associations(复数形式,如果我没记错的话,它是一个数组)

2)你还可以尝试设置一个默认的per_page和一个可选的per_page,甚至可以进行聚合,例如使用per_page_parts_auditions代替同时使用per_page_parts和per_page_auditions。如果你的API是设计给公众使用的,我不会这样做,因为这样会使使用更容易但理解更困难。但根据你的发布,这是一个私有API... 这应该是避免重复的好方法。


1/ 同意(它是一个集合的数组..基本上是SQL关系) 2/ 已经有一个默认的每页显示数量(你不需要定义它,但你可以 - 还有{association}_per_page默认值,我只是想向你展示一些用例),而且我不能真正使用per_page_parts_auditions,因为我只向你展示了2个关联,但实际上还有很多其他的关联和不同的集合(所有这些都有不同的关联)。我们的{association}_per_page参数是动态生成的。 - Mike
由于您的 {association}_per_page 参数是动态生成的,您能否将其更改为 {associations}_per_page,并在代码中调用 {association}_per_page 代码? - Diego Dias
抱歉,我不理解最后一个问题,我已经在询问 {association}_per_page 了。 - Mike

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接