API 路由命名约定

API routes naming convention

我正在为一个私人项目开发 API(连同 SPA),我无法在两种路由命名约定之间做出决定。

假设我的数据库中有三个 table:UsersProductsOrders。如果我希望用户能够订购产品,我应该遵循以下哪一项约定?

  1. POST /orders 与 body { "product": 1 }
  2. POST /products/{id}/order

注意:在这两种情况下,user 将根据提供的访问令牌进行推断。

对我来说,上述两种解决方案的主要区别在于向 front-end 开发人员公开的接口类型:我是否向 资源公开路由(解决方案 1)或 要执行的操作(解决方案 2)?

使用一种方法相对于另一种方法是否有实际的(缺点)优势,或者这只是个人品味的问题?

如果我错了请纠正我,但根据我的理解,解决方案 1 是 REST ("create this resource"),而解决方案 2 不是 ("perform this action")。

此外,对于解决方案 1,每个路由都将直接映射到我数据库中的 table,有些人说这是个坏主意,因为外部开发人员随后可以根据 API 推断数据库的架构路线,但老实说,我不明白这是怎么回事。

Are there actual (dis)avantages to use one method over the other or is it just a matter of personal taste?

拼写的选择主要是品味和惯例。从客户端的角度来看,这两个都是不透明的 URI,可用于遵循您的协议。拼写约定适用于人类读者,并使端点的实现更容易。

Correct me if I'm wrong, but from my understanding solution 1 is REST ("create this resource") while solution 2 isn't ("perform this action").

不,但这是一个常见的误解。

REST 架构风格对 "how does the client know which uri to follow" 和 "how does the client know what media type should be used in the payload" 这样的问题比对拼写更感兴趣。

您可能需要注意的是 URI 标识您的 资源 ,而不是您的资源恰好与之通信的域模型实体。

Also, with solution 1 each route would directly map to a table in my database and some people say it's a bad idea cause external developers can then infer the database's schema based on the API routes but honestly I don't see how it's a problem.

换句话说 - 当您想要修改架构时,您是否打算必须重写所有客户端?还是您打算将客户端与域的实现细节分离?

想想四人组的适配器模式——你给你的客户一个设计良好、稳定、api 他们可以与之通信的,以及你的资源的实现,你调整你得到的请求您模型的当前实现。

Fielding, 2008

REST is software design on the scale of decades: every detail is intended to promote software longevity and independent evolution.

记住:如果这些属性对您不重要,如果它们不支持您当前的价值主张,那么您需要用这些限制换取更合适的东西。

TL;DR

根据我的研究以及 GitHub 和 Instagram API 的端点,对于用户订购产品最有意义的是公开 POST /users/123/orders {"product": 456} 而不是 POST /orders {"product": 456, "user": 123}这里的想法是考虑资源的上下文,如果有的话。

来源

Best Practices for Designing a Pragmatic RESTful API

Notice that we don't need to use the 'update' verb phrase in the URL because we can rely on the HTTP verb to inform that operation. Just to clarify, the following resource URL is redundant:

PUT http://api.example.com/customers/12345/update

With both PUT and 'update' in the request, we're offering to confuse our service consumers! Is 'update' the resource?

10 Best Practices for Better RESTful API

4. Use sub-resources for relations

If a resource is related to another resource use subresources.

GET /cars/711/drivers/ Returns a list of drivers for car 711
GET /cars/711/drivers/4 Returns driver #4 for car 711

GitHub and InstagramAPIs

GitHub 和 Instagram APIs 似乎也以这种方式工作,即在相关时使用资源的 context

例如,如果您想使用 GitHub 的 API 获得 list of a user's organizations,您将使用 GET /users/flawyte/orgs 而不是 GET /orgs {"username": "flawyte"}

与 Instagram 的 API 相同,如果您想喜欢媒体:POST /media/{media_id}/likes