【问题标题】:URL design for an APIAPI 的 URL 设计
【发布时间】:2011-05-23 12:46:21
【问题描述】:

我正在为我们的后端开发一个私有 API。
我的收藏有关联。
每个集合都可以请求,分页,也可以请求关联,对关联进行分页。

我们不确定要使用哪种 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 方案吗?

谢谢!

【问题讨论】:

    标签: ruby-on-rails http api rest restful-url


    【解决方案1】:

    我的回答:/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+params 进行缓存)。我不想为每个关联单独调用(这就是为什么我的 API 不是完全安静的原因),这意味着要进行多次调用以获取一些信息,而我什至不使用缓存...
    • 我在上面的回复中添加了我的回复(斜体)。
    【解决方案2】:

    【讨论】:

    • 嗨,Marcus,感谢您的跟进并将其标记为 restful-url,我没有找到任何有关在 API 中使用数组的有用帖子。而且我不确定这个 API 是否可以归类为 RESTful API,我们不想嵌套所有内容……否则要从集合中获取 2 个关联,我们必须进行 2 次调用,而我们并不真正想要那个。
    【解决方案3】:

    我会选择第一个。我不喜欢在 url 上看到 [] 符号,恕我直言,这让客户更难使用和理解。一些更改作为建议。

    1) 由于关联似乎是一个数组,因此更改关联(复数,如果我是对的并且它是一个数组)

    2) 您也可以尝试放置一个默认的 per_page 和一个可选的,甚至是聚合的,例如 per_page_parts_auditions,而不是同时使用 per_page_parts 和 per_page_auditions。如果您的 API 设计为公开的,我不会这样做,因为它更易于使用但更难理解,但正如您发布的那样,它是私有的......应该是避免复制的好方法。

    【讨论】:

    • 1/ 同意(它是一个集合数组......基本上是 sql 关系) 2/ 已经有一个默认的 per_page(您不需要定义它,但您可以 - 还有 {association}_per_page 默认值我只是想向您展示一些用例)并且我不能真正使用 per_page_parts_auditions 因为我只向您展示了 2 个关联,但实际上还有更多,而且我有大量不同的集合(都有不同的关联)。我们的 {association}_per_page 参数是动态生成的。
    • 由于您的 {association}_per_page 参数是动态生成的,您不能将其设为 {associations}_per_page 并在您的代码中调用 {association}_per_page 代码吗?
    • 对不起,我没有得到最后一个问题,我已经在询问 {association}_per_page ..
    猜你喜欢
    • 2020-09-18
    • 2018-02-11
    • 1970-01-01
    • 1970-01-01
    • 2021-08-13
    • 1970-01-01
    • 1970-01-01
    • 2013-10-10
    • 2012-11-02
    相关资源
    最近更新 更多