不同的API URL构建方法之间有哪些权衡:子域名 vs 子目录以及版本控制?

70
我们有一个域名为 example.com 的web应用程序。现在,我们想将这个应用程序的一部分扩展为REST API,并且正在就最佳URL模式展开讨论。
我们可以使用URL模式 api.example.comexample.com/api。如果有,需要考虑什么权衡?
此外,关于API版本控制的方法,需要考虑哪些权衡?它可以通过URL(v1.api.example.comexample.com/api/v1 或一些奇怪的混合形式)来完成。或者,也可以通过HTTP请求头(或其他方式)来完成。

在其他公司的资产或开发团队的任何其他地方有过任何先前的经验吗?两种选择都可以。 - Andrew
5
两者都可以,我们在某个项目中选择了api.XXXXX.com格式。 - Arun P Johny
即使我们在工作中进行了相同的讨论,我们还是选择了api.xxxx.com。这种方法似乎更整洁。现在我们为API集群设置了不同的配置。 - Srinivas
6
主要区别在于,api.example.com会添加CORS请求,而example.com/api不会。 - aarjithn
是的,api.example.com 添加了CORS,它会成为性能瓶颈吗? - codeaprendiz
3个回答

22

这要看你的需求。

如果你使用http://api.example.com,它会将你的API作为子域名。基本上,如果你的REST服务需要被多个客户端使用,这种URL模式是很好的选择,但如果只有一个客户端连接到你的API,那么http://example.com/api/v1这种模式就更适合。不过,如果你想添加更多的API,并且有更多的客户端连接到它,最好还是使用http://example.com/api/v1这种模式。例如,考虑以下情况。

http://example.com/reportapi/apioperation?parameters

http://example.com/paymentapi/apioperation?parameters

http://example.com/searchapi/apioperation?parameters

最后但同样重要的是,PayPal使用模式http://example.com/api/v1


25
Paypal的API有点陈旧。Stripe使用api.stripe.com,甚至Stack Overflow也使用api.stackoverflow.com。 - Srinivas
10
PayPal不使用那种模式。PayPal使用 https://api.[sandbox].paypal.com/v1/ 这种模式。 - Green
2
GitHub也是:https://api.github.com - Maicon Heck

4
我认为你应该考虑不使用http://api.example.comhttp://example.com/api/v1。相反,我建议使用http://example.com/api和内容协商进行版本控制。以下是我的想法:
使用子域名: 根据URI Scheme Specification,您正在在URI的权限部分定义API,该部分用于定义主机,而不是在主机上定义应用程序或API。实际上,您正在为API创建不同的地址,这意味着针对api.example.com的身份验证可能无法像example.com一样工作。 这样做的一个有效原因可能是设计移动设备的新实例,例如mobile.example.com,但我认为这更多是基础架构决策,而不是功能决策。
在主域上使用未命名路径: 这里有两个信息:一个是指示存在API资源,另一个是该API资源的版本号(v1)。

使用/api/来区分API和例如在/web/下运行的Web视图并没有什么不好的。这可以被认为是常见的最佳实践。

我不确定你是否有意,但是你的问题包括如何解决API版本控制的查询。个人认为,API版本控制不应该使用URL,因为它们旨在尽可能长时间保持稳定。Cool URIs don't change!相反,考虑使用HTTP Content-Type信息来对API进行版本控制。我在VMware documentation中发现了这种方法的使用。此外,这里有一篇相当古老但仍然有用的关于内容类型版本控制的文章,作者是Peter Williams


15
我觉得在URL中使用版本控制比使用Content-Type更符合“Cool URIs don’t change”的理念。为什么呢?假设你在未来的一个发布版本中将用户模型的名称更改为“person”,那么你只需将“users”重定向到“people”。然后,在某个时候,你决定添加一个名为“users”的新模型。现在,你被迫更改URL。相反,你可以从一开始就在URL中使用版本控制。经过100次发布,如果你保持v1 API工作正常,那么所有v1链接的工作方式都将完全相同。简单点说,URL比标题大多数情况下更容易更改。 - Ben Aubin
9
绝对不同意这个答案。Ben的评论有点接近,但并不是很清楚。重要的是,当某人基于您的API构建应用程序功能时,他们需要确保您的API始终接受他们提供的内容并返回他们期望的结果。如果您不对URL进行版本控制,那么随着您的内部实现不断成熟和变化,给定的URL将不可避免地开始漂移。 - kael
4
完全不同意。如果需要的话,身份验证可以在所有子域上工作。但是,通常情况下,您不希望为API(例如API密钥)使用相同的身份验证。此外,HTTP内容类型解决方案过于复杂,而且不同版本的API可能不会使用相同的URL。您最终将陷入共享URL和某些特定URL的混乱局面:/ - Profet
我认为这些答案在某些方面是正确的,但也有错误的地方。首先,我们现在绝对可以处理跨域身份验证和授权。虽然我理解Ben、Kael和Profet的观点,但我会挑战他们思考URI是什么。URI不仅仅是URL栏中的字符串或请求目标,它还包括元数据。例如,您想要底层资源的哪个表示形式等元数据。请记住,URI不是资源本身,它们是一个标识符,可以指向不同的表示形式。 - jamesconant
此外,声明您要请求哪种表示形式可以通过向URL字符串添加更多信息或使用内容协商来完成。严格来说,仅具有“/api/v1/posts”并不意味着您始终获取帖子的完全相同的表示形式,因为可能已经进行了次要和补丁版本更新,但这些更新并没有破坏原有的数据结构。我认为这是一个看起来似乎更容易理解的情况(即URL版本控制),但如果我们稍微思考一下,就会意识到它与将相同的数据放在其他地方并没有太大区别。 - jamesconant

0

这是一个权衡取舍的案例,没有单一的最佳解决方案。

例如,如果您的 http://example.com/ 通过标准网络界面和 API 提供内容,则需要类似于 http://api.example.com/api/<version>/<the usual resource pattern> 的东西,仅用于将基于浏览器的应用程序访问与 API 交互分开。这有意义吗?

例如: api.rottentomatoes.com

但是,即使您的域名专门用于 API 调用,仍然有意义使用上述模式,并将 http://example.com/ 保留用于与您的应用程序进行其他方式的交互。例如,您可能需要http://example.com/mobile/等。


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