【发布时间】:2011-10-30 15:42:06
【问题描述】:
我们都喜欢 REST,尤其是在 API 开发方面。在过去的几年里,我总是偶然发现同样的问题:嵌套资源。似乎我们生活在天平的两个边缘。让我介绍一个例子。
/galaxies/8/solarsystems/5/planets/1/continents/4/countries.json
尼托。类似的情况似乎无处不在,无论它们以何种形式出现。现在,我希望能够获取太阳系中的所有国家,同时能够获取如上所示的深度范围的国家。
看来我在这里有两个选择。第一个,我扁平化了我的嵌套结构并引入了很多 GET 参数(需要我的 API 用户详细记录和理解),如下所示:
/countries.json?galaxy=8&solarsystem=5&planet=1&continent=4
我可以像这样展平我所有的资源,并为每个资源赢得一个唯一的端点基础 URL。好点……每个资源的唯一端点!
但是价格是多少?感觉不自然的东西,是不可发现的,并且不像我的资源下面的树结构。结论:坏主意,但实践良好。
另一方面,我可以尝试摆脱尽可能多的额外 GET 参数,创建这样的端点:
/galaxies/8/solarsystems/5/countries.json
但我也需要:
/galaxies/8/solarsystems/5/planets/1/continents/4/countries.json
这似乎是天平的另一面。额外的 GET 参数数量最少,行为更自然,但仍然不是我作为 API 用户所期望的。
去年我使用的大多数 API 都遵循一种或另一种范式。似乎至少有一颗子弹可以咬。那么为什么不做以下事情:
如果存在自然嵌套的资源,让它们完全按照我们期望的嵌套方式嵌套。当我们保持这种状态时,我们首先实现的是每个资源的唯一端点:
/galaxies.json
/galaxies/8/solarsystems.json
/galaxies/8/solarsystems/5/planets.json
/galaxies/8/solarsystems/5/planets/1/continents.json
/galaxies/8/solarsystems/5/planets/1/continents/4/countries.json
好的,但是如何解决最初的问题,我想获取一个太阳系中的所有国家,同时仍然能够获取完全覆盖在星系、太阳系、行星和大陆下的国家?这对我来说很自然:
/galaxies/8/solarsystems/5/planets/0/continents/0/countries.json # give me all countries in the solarsystem 5
/galaxies/8/solarsystems/0/planets/0/continents/0/countries.json # give me all countries in the galaxy 8
……等等,等等。现在你可能会争辩说“好吧,但是那里的零……”你是对的。看起来不是很好。那么为什么不把上面的两个调用改成这样:
/galaxies/8/solarsystems/5/planets/all/continents/all/countries.json # give me all countries in the solarsystem 5
/galaxies/8/solarsystems/all/planets/all/continents/all/countries.json # give me all countries in the galaxy 8
整洁吧?那么我们要达到什么目的呢?每个资源端点没有额外的 GET 参数和仍然稳定的基本 URL。价钱多少?是的,至少 URL 更长,尤其是在使用 curl 等工具进行手动测试时。
我想知道这是否是一种不仅可以提高 API 的可维护性,还可以提高 API 易用性的方法。如果是这样,为什么没有人采取这样的方法。我无法想象成为第一个有这个想法的人。因此,对于这样的方法,必须有有效的反驳论据。我没有看到。你?
我真的很想听听您支持或反对这种方法的意见和论据。也许有改进的想法……很高兴收到您的来信。在我看来,这可能会导致更好的结构化 API,因此希望有人会阅读并回复。
问候。 一月
【问题讨论】:
标签: ruby-on-rails api http rest