将资源链接到另一个资源时使用 POST 路由
using a POST route when linking a resource to another one
假设您有两个实体 Product
和 Category
。一个产品可以有多个类别,一个类别可以有多个产品。
当谈到 API 设计时,您想要创建端点以在产品中添加/删除类别。第一种方法是这个
- POST/products/:productId/categories/:categoryId
- 删除 /products/:productId/categories/:categoryId
这很好,但我通常使用 POST 创建新资源并发回 201。另一种方法是
- 补丁/产品/:productId/categories/:categoryId
如果您想添加/删除它,请发送一个布尔值。第二种方法似乎更合适(只是 return 一个 200)但是主体有效载荷看起来有点难看。
{
"add": true
}
或者在没有主体有效负载的情况下调用补丁路由,然后切换它?如果该产品链接到类别,请将其删除,否则添加。
从另一个资源中添加/删除资源的最佳做法是什么?
我建议您阅读 Jim Webber 的 2011 talk。
如果我们在做 REST,那么我们就是在使用通用消息语义来实现我们的目标。当 HTTP 是我们选择的应用程序时,我们的通用消息语义是那些与通过网络传输文档相关联的语义。
您通过对资源提出更改建议来向系统传递信息。
一种常见的更改形式是修改资源的表示形式。在您的情况下,这将建议一个资源,该资源是与产品关联的所有类别的列表。因此,您将 GET
该资源的当前表示,对您的副本进行本地更改,然后 PUT
您更新后的表示返回到相同的资源。
GET /products/1/categories
200 OK
Content-Type: text/plain
A
B
C
D
PUT /products/1/categories
Content-Type: text/plain
A
B
E
F
G
200 OK
当资源的表示非常大(相对于 HTTP headers 的大小),而你想要支持的编辑通常会很小,那么支持就有意义了PATCH,接受一种标准化的补丁文档格式。
另一种方法是 POST 给资源一个描述要进行的某些更改的文档。参见 It is okay to use POST,罗伊·菲尔丁 (Roy Fielding):
POST serves many useful purposes in HTTP, including the general purpose of “this action isn’t worth standardizing.”
大多数 pre-javascript HTML 网络都是这样工作的; HTML 表单会告诉客户如何创建目标资源知道如何解释的 application/x-www-form-urlencoded
文档。
POST /products/1/categories
Content-Type: application/x-www-form-urlencoded
remove=C,D&add=E,F,G
效果很好;网络取得了灾难性的成功。
表单之所以有效,是因为 text/html 媒体类型具有标准化的表单定义以及处理方式。您可以对自己的媒体类型做类似的事情;在表示中定义如何找到有趣的 link 来宣传某些资源的功能。
另一种方法是使用[web links];您定义 link 关系
的语义
the relation http://example.org/abc
indicates that the target resource is capable of understanding and handling POST requests containing application/prs.xyz+json
documents)
然后您将这些 link 关系嵌入到您的表示中,嵌入到 HTTP headers 中,或同时嵌入到两者中。然后,任何了解 link 关系语义和相关媒体类型的客户端都将能够利用所宣传的功能。
请参阅 RFC 5023 了解如何在 Atom 中应用此方法。
假设您有两个实体 Product
和 Category
。一个产品可以有多个类别,一个类别可以有多个产品。
当谈到 API 设计时,您想要创建端点以在产品中添加/删除类别。第一种方法是这个
- POST/products/:productId/categories/:categoryId
- 删除 /products/:productId/categories/:categoryId
这很好,但我通常使用 POST 创建新资源并发回 201。另一种方法是
- 补丁/产品/:productId/categories/:categoryId
如果您想添加/删除它,请发送一个布尔值。第二种方法似乎更合适(只是 return 一个 200)但是主体有效载荷看起来有点难看。
{
"add": true
}
或者在没有主体有效负载的情况下调用补丁路由,然后切换它?如果该产品链接到类别,请将其删除,否则添加。
从另一个资源中添加/删除资源的最佳做法是什么?
我建议您阅读 Jim Webber 的 2011 talk。
如果我们在做 REST,那么我们就是在使用通用消息语义来实现我们的目标。当 HTTP 是我们选择的应用程序时,我们的通用消息语义是那些与通过网络传输文档相关联的语义。
您通过对资源提出更改建议来向系统传递信息。
一种常见的更改形式是修改资源的表示形式。在您的情况下,这将建议一个资源,该资源是与产品关联的所有类别的列表。因此,您将 GET
该资源的当前表示,对您的副本进行本地更改,然后 PUT
您更新后的表示返回到相同的资源。
GET /products/1/categories
200 OK
Content-Type: text/plain
A
B
C
D
PUT /products/1/categories
Content-Type: text/plain
A
B
E
F
G
200 OK
当资源的表示非常大(相对于 HTTP headers 的大小),而你想要支持的编辑通常会很小,那么支持就有意义了PATCH,接受一种标准化的补丁文档格式。
另一种方法是 POST 给资源一个描述要进行的某些更改的文档。参见 It is okay to use POST,罗伊·菲尔丁 (Roy Fielding):
POST serves many useful purposes in HTTP, including the general purpose of “this action isn’t worth standardizing.”
大多数 pre-javascript HTML 网络都是这样工作的; HTML 表单会告诉客户如何创建目标资源知道如何解释的 application/x-www-form-urlencoded
文档。
POST /products/1/categories
Content-Type: application/x-www-form-urlencoded
remove=C,D&add=E,F,G
效果很好;网络取得了灾难性的成功。
表单之所以有效,是因为 text/html 媒体类型具有标准化的表单定义以及处理方式。您可以对自己的媒体类型做类似的事情;在表示中定义如何找到有趣的 link 来宣传某些资源的功能。
另一种方法是使用[web links];您定义 link 关系
的语义the relation
http://example.org/abc
indicates that the target resource is capable of understanding and handling POST requests containingapplication/prs.xyz+json
documents)
然后您将这些 link 关系嵌入到您的表示中,嵌入到 HTTP headers 中,或同时嵌入到两者中。然后,任何了解 link 关系语义和相关媒体类型的客户端都将能够利用所宣传的功能。
请参阅 RFC 5023 了解如何在 Atom 中应用此方法。