将资源链接到另一个资源时使用 POST 路由

Posted

技术标签:

【中文标题】将资源链接到另一个资源时使用 POST 路由【英文标题】:using a POST route when linking a resource to another one 【发布时间】:2020-06-10 19:04:30 【问题描述】:

假设您有两个实体ProductCategory。一个产品可以有多个类别,一个类别可以有多个产品。

当涉及到 API 设计时,您希望创建端点以在产品中添加/删除类别。第一种方法是这样的

POST /products/:productId/categories/:categoryId 删除 /products/:productId/categories/:categoryId

这很好,但我通常使用 POST 创建新资源并发送回 201。另一种方法是

PATCH /products/:productId/categories/:categoryId

如果你想添加/删除它并发送一个布尔值。第二种方法似乎更适合(只返回 200),但 body 有效载荷看起来有点丑。


    "add": true

或者调用没有正文有效负载的补丁路由并切换它?如果该产品链接到该类别,则将其删除,否则添加。

从另一个资源中添加/删除资源的最佳做法是什么?

【问题讨论】:

【参考方案1】:

我建议您查看 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 标头的大小),并且您想要支持的编辑通常会很小,那么支持 PATCH 是有意义的,接受其中一个标准化补丁文件格式。

另一种方法是向资源发布一个描述要进行的更改的文档。请参阅 It is okay to use POST,作者 Roy Fielding:

POST 在 HTTP 中有许多有用的用途,包括“此操作不值得标准化”的一般用途。

这就是大多数 pre-javascript html web 的工作方式; 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 媒体类型有一个标准化的表单定义,以及如何处理它们。你可以用你自己的媒体类型做类似的事情;在表示中定义如何找到宣传某些资源功能的有趣链接。

另一种方法是使用[网页链接];您定义链接关系的语义

关系http://example.org/abc表示目标资源能够理解和处理包含application/prs.xyz+json文档的POST请求)

然后您将这些链接关系嵌入到您的表示中,或嵌入到 HTTP 标头中,或两者兼而有之。然后,任何了解链接关系语义和相关媒体类型的客户端都将能够利用所宣传的功能。

请参阅RFC 5023,了解如何在 Atom 中应用这种方法。

【讨论】:

以上是关于将资源链接到另一个资源时使用 POST 路由的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 5:无法发布路由资源

将子网添加到另一个资源组中的vnet

ExpressJS - 嵌套/链接资源的 RESTful 路由设计

REST API 设计 - 最佳实践:链接现有子资源 [关闭]

宁静服务的路由策略

微众WeCross 跨链平台跨链路由