如何定义我的 REST API?
How can I define my REST API?
我有 3 个模型:tournament、championship 和 competitor:
- 一个锦标赛有很多锦标赛;
- 一个冠军属于锦标赛;
- 一个冠军有很多竞争对手。
因此,要列出所有锦标赛的所有参赛者,URL 是:
GET https://base.com/tournament/{slug}/competitors
但是要加一个参赛者,是和冠军有关的所以:
POST https://base.com/championships/{id}/competitors
对于同一个模型,两个动词(GET 和 POST)有不同的 URI 可以吗?否则,我该怎么办?
我爱上了:
POST https://base.com/tournaments/{slug}/championships/{id}/competitors
没有必填字段。
Is it ok that for the same model, two verbs (GET
and POST
) has differents URI?
这可能会给 API 消费者造成混淆,因此我建议您使用相同的 URI。
请记住,Roy T. Fielding 的论文 chapter 5 中描述的 REST 架构风格为构建在顶层的应用程序定义了一组约束这样的架构。但是它没有关于 URI 必须是什么样的。
Martin Fowler 撰写的 popular article 中的示例解释了 Leonard Richardson 定义的模型 建议 一个看起来友好且易于阅读的 URI 结构。虽然它可能是理想,但对于 REST 应用程序来说并不是强制性。
您可以采用许多有效的方法。如果竞争对手需要锦标赛存在,而锦标赛需要锦标赛 存在,你可以这样表达 hierarchy 使用:
/tournaments/{slug}
/tournaments/{slug}/championships/{id}
/tournaments/{slug}/championships/{id}/competitors/{id}
但最后一个URI可能会被认为太长,可能难以记住。所以你可以简单地拆分它,然后你不需要发送很多参数:
/tournaments/{slug}
/championships/{id}
/competitors/{id}
如果您需要执行任何过滤,您可以使用 query parameters。例如:
/championships/{id}?tournament={slug}
提醒:REST 不关心 URI 的拼写方式
Is it ok that for the same model, two verbs (GET and POST) has differents URI? Otherwise, how should I do?
没关系,但会产生一定的费用。
让我们回顾一下菲尔丁 (2008) 所说的话
REST is intended for long-lived network-based applications that span multiple organizations.
The REST interface is designed to be efficient for large-grain hypermedia data transfer, optimizing for the common case of the Web, but resulting in an interface that is not optimal for other forms of architectural interaction.
菲尔丁在他的论文中确定的复制方式之一是 the cache; he goes on to add that style to his definition of REST
In order to improve network efficiency, we add cache constraints to form the client-cache-stateless-server style.... Cache constraints require that the data within a response to a request be implicitly or explicitly labeled as cacheable or non-cacheable. If a response is cacheable, then a client cache is given the right to reuse that response data for later, equivalent requests.
在 HTTP 中,缓存的语义在 RFC 7234; Section 4.4 describes invalidation 中定义。
A cache MUST invalidate the effective Request URI (Section 5.5 of [RFC7230]) as well as the URI(s) in the Location and Content-Location response header fields (if present) when a non-error status code is received in response to an unsafe request method.
这意味着通过 generic 客户端的通信,对您的协议的细节一无所知,可以根据请求中的元数据使他们陈旧表示的本地副本无效和响应。
(在过去,当我们没有加密所有流量时,这是一个更大的问题;但它仍然适用于 (a) 客户端的本地缓存和 (b) 位于客户端前面的缓存反向代理领域模型)。
就REST而言,URI是不透明的;
之间没有根本关系
/A
/A/B
/A/B/C
/A/B/D
/A/E
因此,如果缓存发现 /A/B
应该无效,他们可以这样做,但他们不会对其他 URI 做任何事情。
对于 PUT、DELETE、PATCH——这些方法的语义非常特定于有效请求 URI。
如果您将相同的方法应用于 POST,那么您将“免费”获得缓存失效。
浏览一个简单的例子;想象一个网站,我们有
GET /superCoolResource
GET /superCoolResource/editForm
我们想在 /superCoolResource
中引入一些更改,因此我们加载编辑表单并提交....
POST ...?
如果我们 POST 到 /superCoolResource/editForm
,那么我们告诉客户端 表单 的缓存副本应该被重新加载,如果 POST 成功。但这可能不是我们想要的——更有可能的是表单保持不变,而 /superCoolResource 是发生变化的东西。这意味着我们可能想让 /superCoolResource
成为目标 URI
GET /superCoolResource/editForm
200 OK
... <form action="/superCoolResource" method="POST"> ....
神奇的是,当 POST 成功时,客户端的缓存、源服务器的缓存和任何参与对话的中间缓存都知道驱逐它们的 /superCoolResource 的旧副本。
我有 3 个模型:tournament、championship 和 competitor:
- 一个锦标赛有很多锦标赛;
- 一个冠军属于锦标赛;
- 一个冠军有很多竞争对手。
因此,要列出所有锦标赛的所有参赛者,URL 是:
GET https://base.com/tournament/{slug}/competitors
但是要加一个参赛者,是和冠军有关的所以:
POST https://base.com/championships/{id}/competitors
对于同一个模型,两个动词(GET 和 POST)有不同的 URI 可以吗?否则,我该怎么办?
我爱上了:
POST https://base.com/tournaments/{slug}/championships/{id}/competitors
没有必填字段。
Is it ok that for the same model, two verbs (
GET
andPOST
) has differents URI?
这可能会给 API 消费者造成混淆,因此我建议您使用相同的 URI。
请记住,Roy T. Fielding 的论文 chapter 5 中描述的 REST 架构风格为构建在顶层的应用程序定义了一组约束这样的架构。但是它没有关于 URI 必须是什么样的。
Martin Fowler 撰写的 popular article 中的示例解释了 Leonard Richardson 定义的模型 建议 一个看起来友好且易于阅读的 URI 结构。虽然它可能是理想,但对于 REST 应用程序来说并不是强制性。
您可以采用许多有效的方法。如果竞争对手需要锦标赛存在,而锦标赛需要锦标赛 存在,你可以这样表达 hierarchy 使用:
/tournaments/{slug}
/tournaments/{slug}/championships/{id}
/tournaments/{slug}/championships/{id}/competitors/{id}
但最后一个URI可能会被认为太长,可能难以记住。所以你可以简单地拆分它,然后你不需要发送很多参数:
/tournaments/{slug}
/championships/{id}
/competitors/{id}
如果您需要执行任何过滤,您可以使用 query parameters。例如:
/championships/{id}?tournament={slug}
提醒:REST 不关心 URI 的拼写方式
Is it ok that for the same model, two verbs (GET and POST) has differents URI? Otherwise, how should I do?
没关系,但会产生一定的费用。
让我们回顾一下菲尔丁 (2008) 所说的话
REST is intended for long-lived network-based applications that span multiple organizations. The REST interface is designed to be efficient for large-grain hypermedia data transfer, optimizing for the common case of the Web, but resulting in an interface that is not optimal for other forms of architectural interaction.
菲尔丁在他的论文中确定的复制方式之一是 the cache; he goes on to add that style to his definition of REST
In order to improve network efficiency, we add cache constraints to form the client-cache-stateless-server style.... Cache constraints require that the data within a response to a request be implicitly or explicitly labeled as cacheable or non-cacheable. If a response is cacheable, then a client cache is given the right to reuse that response data for later, equivalent requests.
在 HTTP 中,缓存的语义在 RFC 7234; Section 4.4 describes invalidation 中定义。
A cache MUST invalidate the effective Request URI (Section 5.5 of [RFC7230]) as well as the URI(s) in the Location and Content-Location response header fields (if present) when a non-error status code is received in response to an unsafe request method.
这意味着通过 generic 客户端的通信,对您的协议的细节一无所知,可以根据请求中的元数据使他们陈旧表示的本地副本无效和响应。
(在过去,当我们没有加密所有流量时,这是一个更大的问题;但它仍然适用于 (a) 客户端的本地缓存和 (b) 位于客户端前面的缓存反向代理领域模型)。
就REST而言,URI是不透明的;
之间没有根本关系/A
/A/B
/A/B/C
/A/B/D
/A/E
因此,如果缓存发现 /A/B
应该无效,他们可以这样做,但他们不会对其他 URI 做任何事情。
对于 PUT、DELETE、PATCH——这些方法的语义非常特定于有效请求 URI。
如果您将相同的方法应用于 POST,那么您将“免费”获得缓存失效。
浏览一个简单的例子;想象一个网站,我们有
GET /superCoolResource
GET /superCoolResource/editForm
我们想在 /superCoolResource
中引入一些更改,因此我们加载编辑表单并提交....
POST ...?
如果我们 POST 到 /superCoolResource/editForm
,那么我们告诉客户端 表单 的缓存副本应该被重新加载,如果 POST 成功。但这可能不是我们想要的——更有可能的是表单保持不变,而 /superCoolResource 是发生变化的东西。这意味着我们可能想让 /superCoolResource
成为目标 URI
GET /superCoolResource/editForm
200 OK
... <form action="/superCoolResource" method="POST"> ....
神奇的是,当 POST 成功时,客户端的缓存、源服务器的缓存和任何参与对话的中间缓存都知道驱逐它们的 /superCoolResource 的旧副本。